从父级导航嵌入式 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 设置为 allowAll
和 base
将 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 - 使用脚本从父级到子级共享变量的最简单方法
从工作表中的 Google Apps 脚本访问 BigQuery 时需要登录错误