• CORS(跨域资源共享)


    引用自阮一峰的网络日志:http://www.ruanyifeng.com/blog/2016/04/cors.html 侵删

    一、浏览器将CORS请求(通过ajax方式)分成两类:

    1.简单请求:需要同时满足以下两大条件

       1).请求方法为:HEAD、GET、POST之一

       2).HTTP的请求头信息不超出以下字段:Accept、Accept-Language、Content-Language、Last-Event-ID、

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

    2.非简单请求:凡是不同时满足上面两个条件的都属于非简单请求

    二、简单请求

      浏览器直接发出CORS请求,在头信息中添加一个Origin字段:

    // 该站点发送的ajax请求

    GET /x/web-interface/online HTTP/1.1
    Host: api.bilibili.com
    Connection: keep-alive
    Accept: */*
    Origin: https://bangumi.bilibili.com
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
    Referer: https://bangumi.bilibili.com/anime/5978/play
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.8

    通过Origin字段说明本次请求来自哪个源,服务器根据这个值,决定是否同意这次请求

    // 正常的响应头

    HTTP/1.1 200 OK
    Date: Thu, 07 Dec 2017 14:33:56 GMT
    Content-Type: application/json;charset=utf-8
    Content-Length: 269
    Connection: keep-alive
    Access-Control-Allow-Origin: https://bangumi.bilibili.com
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Headers: Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,Access-Control-Allow-Credentials
    X-Cache: BYPASS from cn-sccd2-cmcc-w-02.hdslb.com
    响应头中与CORS请求相关字段
    Access-Control-Allow-Origin: 必须的字段;要求值是请求的Origin的值;或者为*,表示可任意跨域
    Access-Control-Allow-Credentials:可选的字段;布尔值(默认无该字段);表示是否允许发送cookie,默认情况下cookie不包括在CORS请求中;
    若设置为true表示服务器明确许可,cookie可以包含在请求中一同发送给服务器
    Access-Control-Allow-Headers
    Access-Control-Expose-Headers:可选字段;CORS请求时,XHR对象的getResponseHeader() 方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma;
    如果想要拿到其他字段,就需要在这个字段中指定

    如果Origin指定的源不在许可范围,服务器也会返回一个正常的HTTP回应,但是浏览器会发现响应头中没有包含

    指定字段: Access-Control-Allow-Origin字段,或者与请求头中的Origin不匹配,就会知道出错了

    // 通过本地服务器向 发送http://www.bilibili.com/x/web-interface/online ajax请求的请求头

    Accept:*/*
    Accept-Encoding:gzip, deflate
    Accept-Language:zh-CN,zh;q=0.8
    Connection:keep-alive
    Host:api.bilibili.com
    Origin:http://127.0.0.1:7824
    Referer:http://127.0.0.1:7824/hello.html
    User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

    // 通过本地文件 发送http://www.bilibili.com/x/web-interface/online ajax请求的请求头

    Accept:*/*
    Accept-Encoding:gzip, deflate
    Accept-Language:zh-CN,zh;q=0.8
    Connection:keep-alive
    Host:api.bilibili.com
    Origin:null
    User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

    //服务器可以进行响应; 但是因为请求头的Origin和响应头Access-Control-Allow-Origin: https://bangumi.bilibili.com(或响应头无该字段) 不相符,浏览会进行报错;不会处理结果

    HTTP/1.1 200 OK
    Date: Thu, 07 Dec 2017 15:19:21 GMT
    Content-Type: application/json;charset=utf-8
    Content-Length: 269
    Connection: keep-alive
    X-Cache: BYPASS from cn-sccd2-cmcc-w-01.hdslb.com

    三、非简单请求

    非简单请求是一种 对服务器有特殊要求的请求;比如说PUT或DELETE等请求,或者Content-Type字段类型为application/json

    非简单请求会在正是通信之前,增加一次HTTP查询请求(预检preflight)

    询问服务器当前域名是否在服务器许可名单当中,以及可以使用的哪些HTTP动词和字段;只有得到肯定答复,浏览器才会正是的发出ajax请求,否则报错;

    // put 请求

        var url = 'http://api.alice.com/cors';
        var xhr = new XMLHttpRequest();
        xhr.open('PUT', url, true);
        xhr.setRequestHeader('X-Custom-Header', 'value'); // 自定义头
        xhr.send();

    预检请求头

    OPTIONS /cors HTTP/1.1
    Origin: http://api.bob.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: X-Custom-Header
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...

    预检请求的方法是 OPTIONS;表示这个请求是用来询问的,头信息中关键字Origin表示来源

    请求头字段

    1.Access-Control-Request-Method:表示CORS请求会用到哪些HTTP方法

    2.Access-Control-Request-Headers:指定浏览器CORS请求会发送的头信息字段

    预检响应

    服务器确认允许跨域请求时,就可以做出回应

    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:39 GMT
    Server: Apache/2.0.61 (Unix)
    Access-Control-Allow-Origin: http://api.bob.com
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: X-Custom-Header
    Content-Type: text/html; charset=utf-8
    Content-Encoding: gzip
    Content-Length: 0
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: text/plain

    如果浏览器否定预检请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段,浏览器会认定浏览器不太同意预检请求,会触发一个错误

    响应头字段

    1.Access-Control-Allow-Methods:必须字段;逗号分隔字符串;表明服务器支持的所有跨域请求的方法;避免多次预检请求

    2.Access-Control-Allow-Headers:如果请求中包含Access-Control-Request-Headers字段,该字段为必须字段

    3.Access-Control-Allow-Credentials:同简单请求

    4.Access-Control-Max-Age:可选字段;指定预检有效期

     通过预检请求后,以后每次浏览器的CORS请求就和简单请求一样会有一个Origin头信息字段

     //本地非简单请求

    // 本地服务器非简单请求结果

     // 该站点非简单请求

    CORS与JSONP都是用于跨域的,但是更为强大,支持所有类型的HTTP请求;

    而JSONP的优势在于支持老式浏览器,以及向不支持CORS的网站去请求数据

  • 相关阅读:
    MAVEN flex
    计算几何--判断点是否在矩形里
    Maven copy方式列举
    配置 IntelliJ IDEA VM options
    解决访问StackOverFlow太慢的问题
    Android sdk manager 更新 5.0 太难了,终于解决
    为OS X增加环境变量
    激活老电脑的第二春:内存盘为Chrome浏览器做缓存
    Android启动外部应用的方法
    在Activities之间导航
  • 原文地址:https://www.cnblogs.com/tatelZhang/p/8001685.html
Copyright © 2020-2023  润新知