跨域问题

128 阅读3分钟

指一个域下的文档或脚本试图去请求另一个域下的资源,由于浏览器同源策略限制而产生

同源策略: 协议+域名+端口三者相同且必须相同

(1). JSONP实现跨域

    ```
    function handleResponse(response) {
        console.log(response.data);
    }
    var script = document.createElement("script");
    script.src = "http://example.com/jsonp/getSomething?uid=123&callback=hadleResponse"
    document.body.insertBefore(script, document.body.firstChild);
    /*handleResponse({"data": "hey"})*/


    ```

    动态添加`script`的标签,可控的去请求远端js并执行,这种跨域方式只能进行GET请求

    当我们通过新建一个script标签请求时,后台会根据相应的参数来生成相应的JSON数据。比如说上面这个链接,传递了handleResponse给后台,然后后台根据这个参数再结合数据生成了handleResponse({“data”: “hey”})。

    紧接着,这个返回的JSON数据其实就可以被当成一个js脚本,就是对一个函数的调用。
    由于我们事先已经声明了这么一个回调函数,于是当资源加载进来的时候,直接就对函数进行调用,于是数据当然就能获取到了。

(2). CORS跨域

    只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:

    HEAD
    GET
    POST2HTTP的头信息不超出以下几种字段:

    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

    对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个`Origin`字段。`Origin`字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

    如果`Origin`指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含`Access-Control-Allow-Origin`字段,就知道出错了,从而抛出一个错误,被`XMLHttpRequest``onerror`回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

    a. Access-Control-Allow-Origin

        该字段是必须的。它的值要么是请求时`Origin`字段的值,要么是一个`*`,表示接受任意域名的请求。

    b. Access-Control-Allow-Credentials

        该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为`true`,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为`true`,如果服务器不要浏览器发送Cookie,删除该字段即可。另一方面,开发者必须在AJAX请求中打开`withCredentials`属性

    c. Access-Control-Expose-Headers

        该字段可选。CORS请求时,`XMLHttpRequest`对象的`getResponseHeader()`方法只能拿到6个基本字段:`Cache-Control``Content-Language``Content-Type``Expires``Last-Modified``Pragma`。如果想拿到其他字段,就必须在`Access-Control-Expose-Headers`里面指定。上面的例子指定,`getResponseHeader('FooBar')`可以返回`FooBar`字段的值。

    总的来说,CORS实现跨域的方法就是根据请求头的Origin值和响应头的Access-Control-Request-HeadersAccess-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败。

(3). Nginx反向代理接口跨域

    实现思路:通过Nginx配置一个代理服务器(域名与example1相同,端口不同)做跳板机,反向代理访问example2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。