好的,我有一个页面在这个页面上有一个iframe。我需要做的是在iframe页面上,找出主页面的URL是什么。
我四处搜索,我知道这是不可能的,如果我的iframe页面是在不同的域,因为这是跨站脚本。但我读过的所有地方都说,如果iframe页面与父页面在同一个域上,它应该工作,例如:
parent.document.location
parent.window.document.location
parent.window.location
parent.document.location.href
…或者其他类似的组合,因为似乎有多种方法可以获得相同的信息。
不管怎样,问题来了。我的iframe与主页在同一个域上,但不是在同一个SUB域上。举个例子
http:// www.mysite.com/pageA.html
然后我的iframe URL是
http:// qa-www.mysite.com/pageB.html
当我试图从pageB.html (iframe页面)抓取URL时,我一直得到相同的访问拒绝错误。因此,即使子域也可以算作跨站脚本,这是正确的,还是我做错了什么?
对于同一域和不同子域上的页面,可以设置文档。通过javascript的域属性。
父帧和iframe都需要设置它们的文档。域是指它们之间共有的东西。
即。
www.foo.mydomain.com和api.foo.mydomain.com都可以使用foo.mydomain.com或只使用mydomain.com,并且是兼容的(不,出于安全原因,你不能将它们都设置为com…)
另外,请注意文档。领域是一条单行道。考虑按顺序运行以下三条语句:
// assume we're starting at www.foo.mydomain.com
document.domain = "foo.mydomain.com" // works
document.domain = "mydomain.com" // works
document.domain = "foo.mydomain.com" // throws a security exception
现代浏览器也可以使用window。postMessage用于跨起源对话,但它在IE6中不起作用。
https://developer.mozilla.org/en/DOM/window.postMessage
我刚刚发现了一个解决这个问题的简单方法,但我还没有发现任何地方提到它的讨论。它需要控制父帧。
在你的iFrame中,假设你想要这样的iFrame: src="http://www.example.com/mypage.php"
好吧,而不是HTML来指定iframe,使用javascript来为你的iframe构建HTML,通过javascript“在构建时”获得父url,并将其作为url get参数在你的src目标的查询字符串中发送,如下所示:
<script type="text/javascript">
url = parent.document.URL;
document.write('<iframe src="http://example.com/mydata/page.php?url=' + url + '"></iframe>');
</script>
然后,找到自己的javascript url解析函数,解析url字符串,以获得您所追求的url变量,在这种情况下,它是“url”。
我在这里找到了一个很棒的url字符串解析器:
http://www.netlobo.com/url_query_string_javascript.html
是的,如果iframe和主页不在同一个(子)域中,则不允许访问父页面的URL。然而,如果你只需要主页面的URL(即浏览器的URL),你可以试试这个:
var url = (window.location != window.parent.location)
? document.referrer
: document.location.href;
注意:
允许Window.parent.location;它避免了OP中的安全错误,这是由访问href属性引起的:window.parent.location.href导致“Blocked a frame with origin…”
文档。referrer指的是“链接到该页的页面的URI”。如果其他源决定了iframe的位置,则可能不会返回包含的文档,例如:
容器iframe @域1
将子iframe发送到Domain 2
但是在子iframe中。域2重定向到域3(即用于身份验证,可能是SAML),然后域3定向回域2(即通过表单提交(),一种标准的SAML技术)
对于子文件iframe。引用者将是Domain 3,而不是包含的Domain 1
文档。location指的是“一个location对象,它包含关于文档URL的信息”;假定是当前的文档,即当前打开的iframe。当窗口。Location === window.parent。位置,那么iframe的href与包含父元素的href相同。
这个问题有很多答案,但在支持或可靠性方面,没有一个肯定是最好的。
选项
window.location.ancestorOrigins[0] will get the parent url, but this api only works in chromium browsers (see support). this also supports nested iframes, where the bottom most child has access to the urls of each parent iframe.
document.referrer is the most common answer but is not always reliable
navigation inside of the iframe would show the last page instead of the parent frame url
redirects only show the most recent referrer to the current page
if the page reloads itself the referer becomes the page itself
http child with an https parent has an empty string for referrer
不管用的东西
window.parent.location.href。如果父节点和子节点在不同的域中,这个api会被现代浏览器阻塞(见这里),并抛出一个错误。
建议
如果支持,我更喜欢window.location.祖宗起源[0]。文档。推荐器可以工作,但不太可靠,使其成为我的备用选项。如果您确实使用文档引用器,请尝试在第一次加载框架页面时调用它,然后再进行导航或重定向,以获取父地址。
假设你要告诉父页面如何设置iframe,以轻松但不安全的方式获得包含路径和URL参数的完整URL,在指定iframe时包含referrerpolicy=" not - safe- URL ":
<iframe src="https://example.com/innersite" referrerpolicy="unsafe-url" title="My Title"></iframe>
然后你可以得到完整的原始URL:
document.referrer
许多其他答案只有当iframe src与父域相同时才有效。
Fallbacks:
如果存在安全问题,您可以像https://stackoverflow.com/a/5697801/1226799所说的那样进行回退,其中父节点在iframe URL的URL参数中显式地发送其URL,但攻击者可以很容易地伪造这一点。
我相信您还可以使用消息传递并检查事件的起源:https://stackoverflow.com/a/61548595/1226799