浏览器中有 同源策略 ,即一个域下的页面中,无法通过 Ajax 获取到其他域的接口。例如有一个接口http://m.juejin.com/course/ajaxcourserecom?cid=459
,你自己的一个页面http://www.yourname.com/page1.html
中的 Ajax 无法获取这个接口。这正是命中了“同源策略”。如果浏览器哪些地方忽略了同源策略,那就是浏览器的安全漏洞,需要紧急修复。
url 哪些地方不同算作跨域?
- 协议
- 域名
- 端口
但是 HTML 中几个标签能逃避过同源策略——<script src="xxx">
、<img src="xxxx"/>
、<link href="xxxx">
,这三个标签的src/href
可以加载其他域的资源,不受同源策略限制。
因此,这使得这三个标签可以做一些特殊的事情。
<img>
可以做打点统计,因为统计方并不一定是同域的。除了能跨域之外,<img>
几乎没有浏览器兼容问题,它是一个非常古老的标签。<script>
和<link>
可以使用 CDN,CDN 基本都是其他域的链接。- 另外
<script>
还可以实现 JSONP,能获取其他域接口的信息,接下来马上讲解。
但是请注意,所有的跨域请求方式,最终都需要信息提供方来做出相应的支持和改动,也就是要经过信息提供方的同意才行,否则接收方是无法得到它们的信息的,浏览器是不允许的。
解决跨域 - JSONP
首先,有一个概念你要明白,例如访问http://coding.m.juejin.com/classindex.html
的时候,服务器端就一定有一个classindex.html
文件吗?—— 不一定,服务器可以拿到这个请求,动态生成一个文件,然后返回。
同理,<script src="http://coding.m.juejin.com/api.js">
也不一定加载一个服务器端的静态文件,服务器也可以动态生成文件并返回。OK,接下来正式开始。
例如我们的网站和掘金网,肯定不是一个域。我们需要掘金网提供一个接口,供我们来获取。首先,我们在自己的页面这样定义
<script>
window.callback = function (data) {
// 这是我们跨域得到信息
console.log(data)
}
</script>
然后掘金网给我提供了一个http://coding.m.juejin.com/api.js
,内容如下(之前说过,服务器可动态生成内容)
callback({x:100, y:200})
最后我们在页面中加入<script src="http://coding.m.juejin.com/api.js"></script>
,那么这个js加载之后,就会执行内容,我们就得到内容了。
解决跨域 - 服务器端设置 http header
这是需要在服务器端设置的,作为前端工程师我们不用详细掌握,但是要知道有这么个解决方案。而且,现在推崇的跨域解决方案是这一种,比 JSONP 简单许多。
response.setHeader("Access-Control-Allow-Origin", "http://m.juejin.com/"); // 第二个参数填写允许跨域的域名称,不建议直接写 "*"
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
// 接收跨域的cookie
response.setHeader("Access-Control-Allow-Credentials", "true");