问题描述
我可以限制Web App的使用,但不能限制对标记中引用的图像的访问。
现在,我正在使用Google Apps脚本开发Web应用程序。 这是公司的内部应用程序,我必须仔细设置资产的访问权限。
对于App本身,从脚本编辑器的作为Web应用程序部署框,将执行该应用程序设置为我([email protected] )和谁可以以 FOO公司内的任何人的身份访问该应用。
(假设我属于FOO公司。我的Google帐户是[email protected])
现在,当我使用FOO的Google帐户登录时,我可以成功访问Web应用程序。 但是当我没有登录时,我无法访问它。 那就是我想要的。
但是,当我设置标签以在Google云端硬盘中显示jpeg文件时,我必须将图像文件的 Share 设置为 Internet上具有此链接的任何人都可以查看。
当我在Web App项目的HTML中设置标记并将jpeg文件的 Share 设置为 FOO Corporation时-具有此链接的该组中的任何人都可以查看,
标签将不起作用(将返回错误403)。
我想限制图像和Web应用程序的访问权限。 我该怎么办?
如何复制
放入jpeg文件
- 将任何JPEG文件(假设它是baz.jpeg)放入Google云端硬盘
- 右键单击并选择 Share
- 将获取链接设置为 FOO Corporation-具有此链接的该组中的任何人都可以查看
- 双击baz.jpeg预览
- 选择︙ => 在新窗口中打开
- 假设URL是https://drive.google.com/file/d/xxxx_object ID_xxxx / view。记录对象ID(此处为xxxx_object ID_xxxx)
<html>
<head>
<base target="_top">
</head>
<body>
<img src="https://drive.google.com/uc?id=xxxx_object ID_xxxx" width="30" height="30" alt="error alt text">
</body>
</html>
创建Code.gs
- 将Code.gs更改为以下代码
function doGet() { return HtmlService.createHtmlOutputFromFile('index'); }
- 保存
将其发布为Web App
- 选择菜单项发布> 部署为网络应用
- 在部署为网络应用程序框中,将项目版本:设置为新建
- 将以以下身份执行应用程序:我([email protected])
- 将有权访问该应用的人设置为 FOO公司内的任何人
- 点击部署
- 点击消息测试网络应用以获取最新代码 中的文本最新代码
结果-错误
Google (logo) 403. That’s an error. We're sorry,but you do not have access to this page. That’s all we kNow.
更改图像文件的访问权限
- 在Google云端硬盘中,找到图像文件baz.jpeg
- 右键单击并选择 Share
- 将获取链接设置为具有此链接的互联网上的任何人都可以查看。
- 打开带有残破图片图标的Web应用程序选项卡,然后重新加载
- 您看到正确的图像
我想做什么?
我想设置受限图像的访问权限以及Web应用程序(仅FOO公司的用户可以访问)。 我该怎么办?
解决方法
403禁止访问
/uc
端点将文件权限设置为“在此组中”时,即使您已登录G Suite帐户,也会返回403 Forbidden
响应。
解决方法
您可以实现将HTMLImageElement
属性设置为src
的动态附加到图像数据的流程(以字节为基础的64位编码字符串)。这样,您可以限制对Web App和图像的访问,并且仍然能够加载它。
部署Web应用程序时,请确保部署具有对该文件的足够访问权限,例如,当文件具有“具有此链接的该组中的任何人都可以查看”权限时:
以以下身份执行该应用程序:我
中的任何人
谁有权访问该应用:[org]
下面是一个小的概念证明,包括服务器端实用程序和示例HTML文件。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const asyncGAPIv2 = ({
funcName,onFailure = console.error,onSuccess,params = []
}) => {
return new Promise((res,rej) => {
google.script.run
.withSuccessHandler(data => {
typeof onSuccess === "function" && onSuccess(data);
res(data);
})
.withFailureHandler(error => {
typeof onFailure === "function" && onFailure(error);
rej(error);
})
[funcName].apply(null,params);
});
};
const fetchAndAppendImage = async ({ parent = document.body,id }) => {
const data = await asyncGAPIv2({
funcName: "getImageFromDrive",params: [{ id,token }]
});
const img = document.createElement("img");
img.src = data;
parent.append(img);
};
(async () => await fetchAndAppendImage({ id: "id here" }))();
</script>
</body>
</html>
您可以将id传递给服务器端实用程序,使用getFileById
获取文件(本机身份验证流程将确保请求者不会访问他们无法访问的文件),并形成一个通过执行以下操作来获取图像数据字符串:
- 通过将
getBlob
更改为getBytes
,从File
实例中提取原始字节。 - 使用
Utilities
服务的base64Encode
方法将字节转换为base-64编码的字符串,并在data:image/png;base64,
之前加上Data URL方案。如果您的图像具有其他MIME类型,请进行相应的修改。
/**
* @summary gets an image from Google Drive
*
* @param {{
* id : string
* }}
*
* @returns {string}
*/
const getImageFromDrive = ({ id }) => {
try {
const file = DriveApp.getFileById(id);
const bytes = file.getBlob().getBytes();
const data = `data:image/png;base64,${Utilities.base64Encode(bytes)}`;
return data;
} catch (error) {
console.warn(error);
return "";
}
};
注释
- 要使以上功能正常工作,您必须拥有较新的V8 runtime enabled。
- 原因可能是登录到多个帐户中,因为尝试仅通过 登录到具有{in this group“权限的
/uc
端点来访问文件G Suite帐户没有授权问题。
从Oleg Valter's answer开始,并与他讨论,作为一种方法,我建议使用模板HTML。这些方法的起源是奥列格·瓦尔特的答案。修改脚本后,它如下所示。
Google Apps脚本方面:
从:function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
至:
function doGet() {
const id = "###"; // <--- Please set the file ID of the image file.
const html = HtmlService.createTemplateFromFile('index');
html.image = getImageFromDrive({id: id}); // <--- This function is from Oleg Valter's answer.
return html.evaluate();
}
HTML端:
从:<img src="https://drive.google.com/uc?id=xxxx_object ID_xxxx" width="30" height="30" alt="error alt text">
至:
<img src="<?!= image ?>" width="30" height="30" alt="error alt text">
注意:
- 使用了Oleg Valter's answer的
getImageFromDrive
的功能。 - 修改Web应用程序的脚本后,请重新部署Web应用程序为新版本。这样,最新的脚本就会反映到Web应用程序中。请注意这一点。