Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何得知我的网页是被哪个站点嵌入的? #68

Open
lmk123 opened this issue May 31, 2018 · 0 comments
Open

如何得知我的网页是被哪个站点嵌入的? #68

lmk123 opened this issue May 31, 2018 · 0 comments

Comments

@lmk123
Copy link
Owner

lmk123 commented May 31, 2018

现在有一个业务场景如下:

有三个站点,分别是 a.mydomain.com、b.mydomain.com 和 c.mydomain.com,其中 A 和 B 都会将 C 用 iframe 嵌入进来,现在有一个需求是当 C 被 A 嵌入的时候要执行一些逻辑。

从直觉上来看,C 只需要根据域名判断一下就好了:

if (top.location.href === 'a.mydomain.com') {
  // 站点 A
} else {
  // 站点 B
}

但在实际运行中,这样的做法会报错:

Blocked a frame with origin "c.mydomian.com" from accessing a cross-origin frame.

C 在尝试访问父页面时被浏览器阻止了,这里就引申出了浏览器的同源策略:两个页面的协议、域名和端口必须是一致的才可以相互访问对方的内容,但 C 和 A 的域名不相同,所以 C 在访问 A 的 URL 时被浏览器阻止了。

接下来怎么办?

第一种方法:document.referrer

document.referrer 可以获取到是哪个网址打开当前页面的,当 A 使用 iframe 嵌入了 C 时,C 的 referrer 就是 a.mydomain.com,但在使用时我们需要先判断自己是不是被 iframe 嵌入了:

if (top !== window) { // 先判断自己是不是在 iframe 里
  if (document.referrer === 'a.mydomain.com') {
    // 站点 A
  } else {
    // 站点 B
  }
}

这个方法的好处是无需修改其它站点的代码,但也有坏处:如果 A 嵌入了站点 D,然后 D 通过修改 location.href 的方式跳转到了 C,此时 C 的 referrer 就会是 D 而不是 A,这是不符合我们的预期的。

第二种方法:document.domain

document.domian 可以解决第一种方法中的问题。

在文章的开头,由于 A 和 C 的域名不同,所以 C 在读取 top.location.href 时报错了,但其实 A 和 C 都有一个相同的根域:mydomain.com,所以我们可以将 A 和 C 的 document.domain 都改为 mydomain.com,这样这两个站点的域就相同了。

我们首先需要在 A 中添加代码:document.domain = 'mydomain.com',然后在 C 中添加:

document.domain = 'mydomain.com'

// 我们只在 A 中设置了 document.domain,
// 如果父页面是 B 这里仍然会报错,
// 所以用了 try/catch
try {
  if (top.location.href === 'a.mydomain.com') {
    // 站点 A
  }
} catch(e) {
  // 站点 B
}

这样设置以后,C 不仅可以获取到 A 的 URL,同时还可以操作 A 中的 DOM,但它要求两个页面要有相同的根域,而第一种方法不需要。

总结

这两种方法各有利弊,在实际使用中可以根据业务场景酌情选择。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant