将来自 Google Apps 脚本的 JSON 作为“访问网络应用程序的用户”提供服务

Posted

技术标签:

【中文标题】将来自 Google Apps 脚本的 JSON 作为“访问网络应用程序的用户”提供服务【英文标题】:Serving JSON from Google Apps Script as "user accessing the web-app" 【发布时间】:2013-04-25 20:12:23 【问题描述】:

尝试以发出请求的用户的身份提供由 Google Apps 脚本发出的 JSON 请求。想了一会儿,我意识到这是行不通的,因为服务脚本需要被授权以调用他的用户身份运行,所以调用脚本必须添加一些授权信息,它没有,我不知道如何添加该信息(这实际上是我的问题:将哪些信息添加到 http-request,以及从哪里获取它)。

但是,尽管如此,当我从浏览器中调用该服务器时,它仍然有效,因为浏览器(我在其中登录到我的 Google 帐户)在 http-request 中发送了正确的信息以证明它是经过授权的。

这个问题在某种程度上与问题How to use Google Apps Script ContentService as a REST server 相关,但给出的答案正是我不想要的:调用的 JSON-Server 不应在我的帐户下运行,而是在调用用户的帐户下运行并使用该用户资源(scriptdb,驱动器,...)。 所以问题是:如何从一个从谷歌帐户运行的脚本提供该信息到另一个脚本,以便另一个脚本可以在该帐户中运行?我知道使用 gas-libraries 可以解决这个问题,但我希望将它作为 JSON-client/server(主要是为了解耦依赖项)。要添加一些代码(以保持 Stack Overflow-spirit 运行),我的客户:

var scriptUrl="https://script.google.com/macros/s/paperlapapp1231231/exec";
function callIt (nm, args) 
  var a=[nm];
  for (x in args) 
    a.push(args[x]);
  
  return Utilities.jsonParse(UrlFetchApp.fetch(scriptUrl+"?args="
       +encodeURIComponent(Utilities.jsonStringify(a))).getContentText());

function testFunction (p1, p2, p3)  // this is the proxy
  return callIt ("testFunction", arguments);

// Testroutine
function callTest() 
  var r=testFunction (9, "XXXlala", "dudu":1, "dada":"xxx");
  Logger.log ("r="+Utilities.jsonStringify(r));

我的服务器:

function doGet(request) 
  var ret=null;
  try 
    Logger.log ("I got called with "+JSON.stringify(request));
    var args=JSON.parse(decodeURIComponent (request.parameters.args));
    ret=ContentService.createTextOutput(
            JSON.stringify(this[args.shift()].apply (this, args)))
         .setMimeType(ContentService.MimeType.JSON);
  
  catch (e) 
    ret=ContentService.createTextOutput(JSON.stringify(e))
          .setMimeType(ContentService.MimeType.JSON);
  
  return ret;

function testFunction (p1, p2, p3)  // this is the implementation
  var s="testing called p1="+p1+", p2="+p2+", p3="+p3;
  Logger.log (s);
  return testingResult:s;

编辑:

制定了解决方案,但需要 Chrome 扩展程序和中间代理服务器。代码见https://bitbucket.org/pbhd/gas-rest-server-as-calling-user

【问题讨论】:

我也对此感兴趣。但请注意,scriptdb 始终是开发人员资源,脚本是否以用户身份运行并不重要,每个脚本只有一个 db(并且计入开发人员帐户)。 是的,没错,scriptdb 只是一个错误的例子,但所有用户的电子表格等等...... 如果用户没有通过浏览器访问此 API,那么调用 REST API 的客户端应用程序是什么? (androidios、windows?) 【参考方案1】:

编辑:这在以前是不可能的,正如我在下面的回答所反映的那样。 但是,Google 现在确实允许这样做,请参阅 Execution API https://developers.google.com/apps-script/execution/rest/v1/scripts/run


Google Apps 脚本无法做到这一点。如果我理解正确,您正在使用 urlFetch 调用另一个 Google Apps 脚本。

由于 Google Apps 脚本没有 oAuth 范围,因此您无法进行经过身份验证的调用。您只能调用发布为 匿名 的 webapp 服务,因此将始终在所有者权限下运行。

您也不能对库执行此操作,除非初始脚本也以用户权限而不是所有者调用。

【讨论】:

请注意,有些人在网络上阅读依赖计算机翻译,请善意使用完整的单词(即不是“u”)。毕竟这里的目标是帮助别人。 嗯。你理解的没错。但是:我愚蠢的浏览器可以进行那些经过身份验证的调用,即使在重新启动和更改了 IP 地址之后也是如此。那么我的 json-client-script 无法做到的浏览器有什么魔力呢?例如。作为一个黑客,我可以只获取浏览器发送的所有请求标头并让我的客户端也发送它们(尝试这样做,不起作用,但不确定我是否以正确的方式) 那也行不通。您可以从浏览器调用,因为它已保存身份验证。 1该身份验证将过期,因此您无法重复使用它。 2该身份验证可能与IP呼叫相关联,因此您无法将其移动到另一个呼叫者IP。 Hmpf。与此同时,我得到了不同的知识:我复制了在浏览器请求中找到的 cookie HSID、SSID 和 SID,将其放入其他主机发出的请求中,瞧:它起作用了。问题似乎是从脚本中发出的请求:来自 google-landscape 的一些丑陋的伙伴剥离了这些 cookie。另一个问题是使用这种方法将这些 cookie 从浏览器中取出。好吧,无论如何,这将是一个丑陋的黑客,但我认为它可以工作...... 出于安全原因,我知道为什么 google 会阻止您。还有其他方法可以做到这一点。考虑调用 anon gas 并传递一些可以识别用户的安全信息。例如 plus 电子邮件范围的访问令牌。加油从令牌中获取电子邮件,因此现在您知道谁在打电话。就认证而言。现在要访问,请使用该令牌,但您需要通过协议 (urlfetch) 调用 api,而不是使用气体库。去过那里。

以上是关于将来自 Google Apps 脚本的 JSON 作为“访问网络应用程序的用户”提供服务的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JSON 文件转换为使用 Google Apps 脚本分隔的新行?

使用 Google Apps 脚本发布 JSON 数据

来自 Google Apps 脚本的 Jdbc 连接错误

将关联数组转换为数字以在Apps脚本中写入工作表

使用 Google BigQuery / Apps 脚本为插入 Google 表格的数据添加时间戳

Google Apps脚本传递网址参数Google信息中心