同源策略及跨域解决办法略识
-
同源策略:默认情况下,javaScript在发送AJAX请求时候,要求URL的域名、协议、端口号要和当前页面一致。
-
如果有需求跨域请求URL,解决方式:
2.1 通过Flash插件发送HTTP请求,这种方式可以绕过浏览器的安全限制,但必须安装Flash,并且跟Flash交互。不过Flash用起来麻烦,而且现在用得也越来越少了。(不建议)
2.2 通过在同源域名下架设一个代理服务器来转发,js将请求发送到代理服务器上:
'/proxy?url=http://www.test.com.cn'
,代理服务器再将结果返回。这种方法需要服务器端做额外的开发。2.3 JSONP。
原理:实际上利用了浏览器允许跨域引用js资源的方法(如下示例1)。
限制:只能使用GET请求,且要求返回js<!-- 示例1 --> <head> <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script> </head>
实现例子:
// 回调函数 function refresh(data) { let p = document.getElementById('test-jsonp'); p.innerHTML = '当前信息:' + data['0001'].name +': ' + data['0001'].price + ';' + data['002'].name + ': ' + data['002'].price; } /*该URL返回值为: refresh({"0001":{"name": "西红柿","price": "3.0/公斤"},"002": {...});*/ function getPrice() { let js = document.createElement('script'), head = document.getElementsByTagName('head')[0]; js.src = 'http://api/test/money/vegetables/price?callback=refresh'; head.appendChild(js); } //调用getPrice触发即可
2.4 CORS。
CORS全称Cross-Origin Resource Sharing
,是HTML5规范定义的如何跨域访问资源。原理:Origin表示本域,也就是浏览器当前页面的域。当JavaScript向外域(如desc.com)发起请求后,浏览器收到响应后,首先检查
Access-Control-Allow-Origin
是否包含本域,如果是,则此次跨域请求成功,如果不是,则请求失败,JavaScript将无法获取到响应的任何数据。假设本域是my.com,外域是dest.com,只要响应头
Access-Control-Allow-Origin
为http://my.com,或者是*,本次请求就可以成功。这种跨域请求,称之为“简单请求”。简单请求包括GET、HEAD和POST(POST的Content-Type类型仅限
application/x-www-form-urlencoded
、multipart/form-data
和text/plain
),并且不能出现任何自定义头对于PUT、DELETE以及其他类型如
application/json
的POST请求,在发送AJAX请求之前,浏览器会先发送一个OPTIONS请求(称为preflighted
请求)到这个URL上,询问目标服务器是否接受:OPTIONS /path/to/resource HTTP/1.1 Host:dest.com Origin: http://my.com Access-Control-Request-Method: POST
服务器必须响应并明确指出允许的Method:
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://my.com Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS Access-Control-Max-Age: 86400
浏览器确认服务器响应的
Access-Control-Allow-Methods
头确实包含将要发送的AJAX请求的Method,才会继续发送AJAX,否则,抛出一个错误。由于以POST、PUT方式传送JSON格式的数据在REST中很常见,所以要跨域正确处理POST和PUT请求,服务器端必须正确响应OPTIONS请求。