如何将Web App的<img>标记中使用的图像限制为“公司内部的任何人”? Google Apps脚本方面: HTML端:注意:参考:

问题描述

我可以限制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文件

  1. 将任何JPEG文件(假设它是baz.jpeg)放入Google云端硬盘
  2. 右键单击并选择 Share
  3. 获取链接设置为 FOO Corporation-具有此链接的该组中的任何人都可以查看
  4. 双击baz.jpeg预览
  5. 选择 => 在新窗口中打开
  6. 假设URL是https://drive.google.com/file/d/xxxx_object ID_xxxx / view。记录对象ID(此处为xxxx_object ID_xxxx)

  1. 创建一个新的无标题脚本项目
  2. 创建一个index.html文件添加代码
<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

  1. 将Code.gs更改为以下代码

    function doGet() {
      return HtmlService.createHtmlOutputFromFile('index');
    }

  1. 保存

将其发布为Web App

  1. 选择菜单发布> 部署为网络应用
  2. 部署为网络应用程序框中,将项目版本:设置为新建
  3. 以以下身份执行应用程序我([email protected]
  4. 有权访问该应用的人设置为 FOO公司内的任何人
  5. 点击部署
  6. 点击消息测试网络应用以获取最新代码
  7. 中的文本最新代码

结果-错误

    Google (logo)
    403. That’s an error.
    We're sorry,but you do not have access to this page. That’s all we kNow.

更改图像文件的访问权限

  1. 在Google云端硬盘中,找到图像文件baz.jpeg
  2. 右键单击并选择 Share
  3. 获取链接设置为具有此链接的互联网上的任何人都可以查看
  4. 打开带有残破图片图标的Web应用程序选项卡,然后重新加载
  5. 您看到正确的图像

我想做什么?

我想设置受限图像的访问权限以及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获取文件(本机身份验证流程将确保请求者不会访问他们无法访问的文件),并形成一个通过执行以下操作来获取图像数据字符串:

  1. 通过将getBlob更改为getBytes,从File实例中提取原始字节。
  2. 使用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 "";
    }
};

注释

  1. 要使以上功能正常工作,您必须拥有较新的V8 runtime enabled
  2. 原因可能是登录到多个帐户中,因为尝试仅通过 登录到具有{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 answergetImageFromDrive的功能。
  • 修改Web应用程序的脚本后,请重新部署Web应用程序为新版本。这样,最新的脚本就会反映到Web应用程序中。请注意这一点。

参考: