参考链接:https://mp.weixin.qq.com/s/4G_27oRLSMMYBFvtYZgqcg
一、什么是跨域
当两个域名的协议、子域名、主域名、端口号中有任意一个不相同的时候,两者之间的请求便存在跨域。
1、什么是同源策略及其限制内容
同源策略是一种约定,它是浏览器最核心也是最基本的安全功能。如果缺少了同源策略,浏览器很容易遭受XSS、CSRF等攻击。所谓同源是指\'协议+域名(子域名、主域名)+端口号\'三者相同,即便两个不同域名指向同一个IP,也不属于同源。
2、常见的跨域场景
特别说明:
HTML标签中img、link、script的这三个标签允许跨域加载资源
注:
1.请求跨域了,那么请求有没有发出去?
跨域并不是请求发不出,请求能正常发送并且服务器也能正常接收和返回结果,只不过结果被浏览器拦截了。
2.为什么表单方式可以发起跨域请求而Ajax不能?
归根结底,跨域是为了阻止用户读取到另一个域名下的内容。Ajax可以获取响应,浏览器认为不安全拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止CSRF,因为请求已经发出去了。
二、跨域解决方案
1、JSONP
原理:利用script标签没有跨域限制的漏洞,网页可以得到其他动态来源的JSON数据。此方式需要目标服务器支持才能实现。
1.1 Ajax与JSONP对比
原则上两者都是客户端向服务端发送请求并获取服务端返回的数据。但是Ajax属于同源策略,JSONP属于非同源策略。
1.2 JSONP的优缺点
优点:JSONP的兼容性好,能解决大部分主流浏览器的跨域数据访问的问题。
缺点:JSONP仅仅支持get请求,对数据安全性无法保障
1.3 Jquery中ajax通过jsonp获取跨域数据示例
请求方JS代码:
$(function () { $.ajax({ url:\'http://test.cache.com/index/checkjsonp.html\', dataType:\'jsonp\', type:\'get\', jsonpCallback:\'checkCallback\', //自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略 jsonp:"callback", success:function (data) { console.log(data) }, error:function () { alert(\'error\') } }) });
跨域服务器返回PHP代码:
public function checkJsonp() { echo "checkCallback(".json_encode(array(\'success\'=>1)).")"; }
返回结果:
2、HTTP访问控制(CORS)
2.1 原理:
CORS需要浏览器和服务器同时支持,IE8和9需要通过XDomainRequest来实现,存在一定的兼容性问题。
浏览器会自动的进行CORS通信,实现CORS通信的关键在于服务器。只要服务器实现了CORS,也就实现了跨域
2.2 实现:
服务端设置 Access-Control-Allow-Origin 就可以开启CORS。该属性表示那些域名可以访问该网站,如果设置成通配符则表示所有网站均可访问
2.3 示例:
JS代码:
$(function () { $.ajax({ url:\'http://test.cache.com/index/checkjsonp.html\', dataType:\'json\', type:\'get\', success:function (data) { console.log(data) }, error:function () { alert(\'error\') } }) });
PHP代码:
public function checkJsonp() { header("Access-Control-Allow-Origin:http://initial.think6.com"); header(\'Access-Control-Allow-Methods:OPTIONS, GET, POST\'); // 允许option,get,post请求 header(\'Access-Control-Allow-Headers:x-requested-with\'); // 允许x-requested-with请求头 echo json_encode(array(\'success\'=>1)); }
返回结果:
3、WebSocket
原理:WebSocket是一种通信协议,它实现了浏览器与服务器之间的全双工通信(即通信双方可以同时发动和接收信息的信息交互方式)。同时websocket并不实行同源策略,只要服务器支持,它就可以实现跨域通信。
4、Node中间件代理
原理:同源策略是浏览器需要遵循的标准,服务器向服务器请求则无需遵循同源策略,从而实现跨区数据请求。
5、nginx反向代理
实现原理类似于Node中间件,需要搭建一个中转nginx服务器,用于转发请求。使用nginx反向代理实现跨域是最简单的方式,只需要修改nginx服务器配置即可解决跨域问题,支持所有浏览器、session。无需修改代码且不会影响服务器性能。