跨域
说到跨域,不得不聊一下浏览器的“同源策略”。
浏览器安全的基石是"同源政策"(same-origin policy),1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同":
协议相同 域名相同 端口相同
随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
今天的主题是跨域所以只讲第三种行为。
跨域的原因:浏览器的原因:同源策源(服务器并没有限制不能访问)
火狐:
谷歌:
解决方案:
1 让浏览器不做校验(缺点:不可能让每个用户都使用这种方式打开浏览器)
使用前必须关闭所有谷歌浏览器窗口
Chrome --disable-web-security --user-data-dir 命令行打开浏览器(不使用安全策略)
2 规避‘同源策略’,不使用XHR请求,采用jsonp
使用jsonp后上面的type就会变成 script
callback=jQuery21404407734151639556_1442902171702&_=1442902171703
这些都是jquery默认生成的
&_=1442902171703 表示生成一个时间码有助于更新缓存
Jsonp的原理:
利用<script>标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如:
<script src="http://www.example.net/api?param1=1¶m2=2"></script>
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
callback({"name":"hax","gender":"Male"})
这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
Jsonp在浏览器的具体表现
(1) :Web页面上调用js文件时不受是否跨域的影响(不仅如此,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)
(2):跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。
前端代码:
这里的jsonp:’callback’要和后端保持一致
php:
Jsonp的弊端:
(1)服务器需要改动代码支持;
(2)只支持get请求(<script>只支持get获取)
(3)非XHR请求(也是可以跨域的原因),没有了异步,事件等操作
3 服务端处理:a域名调用b域名的时候, b域名返回的数据中加入某些字段告诉浏览器允许a域名调用(支持跨域)
有以下两种策略
(1)程序中设置header
带有cookie的ajax请求指定一下两个属性
php端设置
Access-Control-Allow-Origin 不能为*号
Access-Control-Allow-Credentials:true
PS:非简单请求和简单请求又有所不同
附链接:
http://www.ruanyifeng.com/blog/2016/04/cors.html (浏览器同源策略)
http://www.ruanyifeng.com/blog/2016/04/cors.html (跨域资源共享CORS详解)
(2)Nginx配置文件设置header
4 浏览器处理:通过一个代理,把指定的url转到b域名,浏览器看来属于同一个域名(隐藏跨域)
假设www.a.com调用www.b.com上的一个接口:
很明显出现跨域。
解决方案:nginx反向代理
在a域名下的nginx.conf修改:
这样所有以/api/开头的请求都会被代理到www.b.com/api/下
请求修改:
请求就会指定到www.b.com/api/下的index.php