JS深入基础之跨域、同源策略及跨域实现方式和原理

682 阅读3分钟

跨域、同源策略及跨域实现方式和原理

同源策略是对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字段不匹配或是不包含该字段,浏览器则会抛出一个错误,被XMLHttpRequestonerror回调函数捕获。(注意:不能通过HTTP Response的状态码来识别)

对于非简单请求

浏览器会自动使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。该预检请求中包含有origin、Access-Control-Request-Method、Access-Control-Request-Headers分别说明源站URI、实际请求的方法、实际请求所携带的首部字段。

服务器收到预检请求后检查originAccess-Control-Request-MethodAccess-Control-Request-Headers字段后,回复一个带有Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-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)
}