跨域、同源策略及跨域实现方式和原理
同源策略是对Javascript代码能对哪些web页面进行操作的一条完整安全限制。具体来说,脚本只能读取和所属文档来源相同的窗口和文档属性。
文档的来源包括了协议,主机,以及载入文档的端口。从不同的web服务器载入的文档具有不同的来源。通过通统一主机不同端口的文档也有不同的来源。http和https也有不同的来源。
注意。脚本本身的来源并不重要,重要的是嵌入的界面的来源。
假设一个来自A的脚本被以<script>标签的方式引用到的B的一个web页面中,那么他就可以完整访问这个web页面的文档内容。当脚本打开了另一个来自B 的web页面,他依然可以完整访问这个页面的文档内容,但若是打开C(A也可以),同源策略就会发生作用,阻止访问。
解决方法一:
跨域资源共享: 使用新的请求头Origin和响应头Access-Control-Allow-Origin,他允许服务器显式的列出源,或使用通配符来匹配所有源并允许由任何地址请求文件。
实现方式:
前端不用动,发出一个普通的ajax请求,浏览器会自动加上Origin请求头
后端要设置一个响应头 Access-Control-Allow-Origin:* 这样就可以了
CORS分为两种情况,分为简单请求和非简单请求
对于简单请求
浏览器直接发出CORS请求,即在头部自动加上origin字段,说明来自哪个源(协议 + 域名 + 端口)。
服务器返回一个添加了几个头部信息字段的HTTP Response说明是否可以同意本次请求。其中带有Access-Control-Allow-Origin字段说明指定了允许访问该资源的外域URI(带有通配符*说明允许来自所有域的请求)。如Access-Control-Allow-Origin字段不匹配或是不包含该字段,浏览器则会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。(注意:不能通过HTTP Response的状态码来识别)
对于非简单请求
浏览器会自动使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。该预检请求中包含有origin、Access-Control-Request-Method、Access-Control-Request-Headers分别说明源站URI、实际请求的方法、实际请求所携带的首部字段。
服务器收到预检请求后检查origin、Access-Control-Request-Method、Access-Control-Request-Headers字段后,回复一个带有Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers说明服务器对应允许跨域访问的URI、请求方法以及请求头部字段。
服务器通过了"预检"请求之后,基本和简单请求一样。浏览器每次请求带上origin字段,服务器回应带上Access-Control-Allow-Origin。
解决方法二 :
JSONP
JSONP的主要原理是,<script>标签不受同源策略影响,可加载异域服务器上的js脚本以执行。利用该原理,后端将数据封装成一句js执行语句(函数执行语句)。前端在加载执行该语句时,调用预先声明好的函数,即可完成对数据的处理。
JSONP 只适用于 get
JSONP 实现
//假设后端规定好了包裹的函数名字就叫callback
function getJSONP(url,callback) {
var script = document.createElement('script')
getJSONP['callback'] = function(response){
try{
callback(response)
}
finally{
delete getJSONP['callback']
script.parentNode.removeChild(script)
}
}
script.src = url
script.parentNode.appendChild(script)
}