从父级导航嵌入式 Google Apps 脚本 iFrame

Posted

技术标签:

【中文标题】从父级导航嵌入式 Google Apps 脚本 iFrame【英文标题】:Navigating embedded Google Apps Script iFrame from the parent 【发布时间】:2019-10-17 09:46:36 【问题描述】:

我有一个多页 Web 应用程序。我想在登录后,用户看到他的队友列表并标记他们的出勤状态。我的问题是我无法在 iFrame 而不是谷歌脚本原始版本中显示它。

例如,我想将它添加到我自己的网页中。这两天我无法解决这个问题,我阅读了很多这方面的帖子,还从头开始尝试了另一个应用程序,但还没有运气。

为澄清起见,我正在使用渲染功能将用户重定向到框架内。所以正如@theMaster 提到的,它不是一个多页 Web 应用程序。

这是我的 doGet 和 Render 函数:

function doGet(e)
    // Logger.log(e);
    Route.path("login",loadLogin);  
    Route.path("admin",loadAdmin);  
    Route.path("view",loadView);
    Route.path("form",loadForm);
if (e.parameters.id)
  LastID=e.parameters.id[0]; 

if (e.parameters.t)
  curT=e.parameters.t[0]; 
  
if (Route[e.parameters.v]) 
  return Route[e.parameters.v]();
 else 
  return render('W-home');
      


function render(file, argObject)
    var page = htmlService.createTemplateFromFile(file);
    if (argObject)
        var keys = Object.keys(argObject);
        keys.forEach(function (k)
        page[k]=argObject[k];
        );
    
    var evalPage =page.evaluate();
    // if (!xFrame)return evalPage;;
    return evalPage.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
 

我可以从主页转到登录页面,但在那之后,即使它也不让我去谷歌。在某些情况下也只是在框架内返回一个空白页。

这是我的客户端 javascript 示例代码。

function goToForm(EmpNo) 
  var link = "<?!=ScriptApp.getService().getUrl()?>" + "?v=form&id=" + EmpNo[1] + "&t=" + EmpNo[2];
  location.href = link;
  // I tried different way to see if i can conqure this! 
  // if (clickBTN= 'a') 
  //   window.open(link, "_self");
  //  if (clickBTN= 'b') 
  //   location.href=link;
  //  if (clickBTN= 'c') 
  //   openNewURLInTheSameWindow(link);
  //           

我还有两个全局变量 xFrame 用于将 XframeOptionsMode 设置为 allowAllbase 将 HTM 页面上的基本目标切换为“_top”或“_self”。

【问题讨论】:

经过一番测试,我相信window.postMessage()是唯一的办法。 @TheMaster 我会检查并告诉你。我不熟悉这个;-) 【参考方案1】:

问题:

你可以试试

window.top.location = link;

它将在顶部框架中加载链接。如果您在您的网站中构建网络应用程序本身,那么您应该使用

window.parent.parent.location = link;

但这不起作用,因为沙盒会阻止导航文档中的其他框架。 sandbox="allow-top-navigation" 只允许顶部框架导航而不是中间框架。由于顶部框架是您的网站而不是 script.google.com,因此无法导航,您会收到错误提示

不安全的 JavaScript 尝试从 URL 为 https://*.googleusercontent.com/... 的框架为 URL 为 https://myexamplesite.com... 的框架启动导航 尝试导航的框架被沙盒化,因此不允许导航其祖先。

解决办法:

使用window.postMessage()
  
==================
|Your site       |<-myexamplesite.com [TOP#0]
|                |
| =============  |
| |GASWebApp  |<-|--script.google.com[Frame#1]
| |           |  |
| |=========  |  |
| ||SandBox|  |  |
| ||User   |<-|--|-- Where your html code is
| ||Frame  |  |  |  (*.googleusercontent.com) 
| |=========  |  |   [Frame#2 and #3(Double nested iframe)]
| |           |  |
| =============  |
|                |
|                |
|                |
==================

片段:

沙盒化 Html:

<script>
if(window.parent.parent !== window.top) //if #1 !== top
  //Framed in a another web-app
  //TODO Use proper target origin instead of *
   window.parent.parent.parent.postMessage("[FRAME#1_LINK_TO_CHANGE]","*");//Post to #0

</script>

顶框(#0):

<!-- Frame the Apps script Web-App Frame#1-->
<iframe
  src="https://script.google.com/macros/s/[SCRIPT_DEPLOYMENT_ID]/exec"
  >Loading...</iframe
>
<script type="text/javascript">
  const handleMessage = function(event) 
    if (
      event.origin !==
      'https://[SCRIPT_ORIGIN]script.googleusercontent.com'
    ) 
      alert('Origin Disallowed');
      return;
    
      //TODO Check syntax of event.data before changing iframe src
      document.querySelector('iframe').src = event.data; //Change #1 Link
  ;
  window.addEventListener('message', handleMessage);
</script>

参考资料:

Basic GAS webapp structure

postMessage

iFrame

【讨论】:

嗨,它跳出框架并在顶部显示谷歌笔记!但它至少会返回一些东西。其他三种方法是给我一个空白页! @Mahhdy 你需要删除第三行:location.href=link; 这是我拥有的确切代码。 ` function goToForm(EmpNo) var link = "=ScriptApp.getService().getUrl()?>"+"?v=form&id="+EmpNo[1]+"&t="+EmpNo[2]; window.top.location =链接;` @Mah 你删除了 location.href=link;。你似乎有一个来自*.googleusercontent.com 的嵌套 iframe。如果一切都写得很好,你应该有你的***框架-Your site> iframe>script.google.com>iframe-userframe-*.googleusercontent.com 看起来像 iframe now have it: the allow-top-navigation-by-user-activation attribute has been added to the sandbox 不确定在没有用户交互的情况下它是否可以工作

以上是关于从父级导航嵌入式 Google Apps 脚本 iFrame的主要内容,如果未能解决你的问题,请参考以下文章

python3 - 使用脚本从父级到子级共享变量的最简单方法

在 SwiftUI 中的兄弟姐妹之间从父级共享状态

从工作表中的 Google Apps 脚本访问 BigQuery 时需要登录错误

Google 表单 - 使用 Google Apps 脚本在项目中添加自定义按钮“更多信息”

如何在 swift 中从父视图访问容器视图子视图

在 Google 文档中插入评论