• HTTP学习——跨域资源共享(CORS)


    介绍

    跨域资源共享 (CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。如果浏览器符合服务器的要求,那么它将可以访问此服务器host内的内容

    跨域HTTP 请求的一个例子:运行在 https://a.com 的 JavaScript 代码使用XMLHttpRequest来发起一个到 https://b.com/data.json 的请求。

    但是浏览器会限制JS跨域HTTP的请求,跨域资源共享(CORS)机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行

    通常由axios(AJAX)即内部的XMLHttpRequestFetch APIs发起的跨域HTTP请求需要用到CORS,还有一些Web字体。图像等

    变化

    CORS新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
    另外,有时候,非GET请求需要首先使用OPTIONS方法发起一个预检请求,从而知道服务器是否允许我们跨域请求
    在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 CookiesHTTP 认证 相关数据)。

    简单请求

    不会触发CORS预检请求的请求称为简单请求,要求满足下列所有条件:
    ①使用GET,POST,HEAD
    ②处于下列首部字段内

    Accept
    Accept-Language
    Content-Language
    Content-Type(需要注意额外的限制)

    ③Content-Type 的值仅限于下列三者之一:

    text/plain
    multipart/form-data
    application/x-www-form-urlencoded
    
    • 1
    • 2
    • 3

    ④请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问以及请求中没有使用 ReadableStream 对象

    CORS实例

    比如说,假如站点 https://foo.example 的网页应用想要访问 https://bar.other 的资源。foo.example 的网页中可能包含类似于下面的 JavaScript 代码:

    const xhr = new XMLHttpRequest();
    const url = 'https://bar.other/resources/public-data/';
    
    xhr.open('GET', url);
    xhr.onreadystatechange = someHandler;
    xhr.send();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    那么客户端和服务器之间使用 CORS 首部字段来处理权限:
    请求头:

    GET /resources/public-data/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    Origin: https://foo.example
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请求首部字段 Origin 表明该请求来源于 http://foo.example
    响应头:

    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 00:23:53 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: *
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Transfer-Encoding: chunked
    Content-Type: application/xml
    
    [XML Data]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Access-Control-Allow-Origin: *说明该网站内的该资源可以被任意网址访问
    Access-Control-Allow-Origin: https://foo.example说明该网站内的该资源只能允许来自https://foo.example访问

    预检请求实例

    请求头
    OPTIONS /doc HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    Origin: https://foo.example
    Access-Control-Request-Method: POST
    上面表示实际请求是POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    上面表示将会携带自定义的2个头
    
    响应头
    HTTP/1.1 204 No Content
    Date: Mon, 01 Dec 2008 01:15:39 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: https://foo.example
    上面表示允许访问的origin
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    上面表示允许的几个发送信息方式
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    上面表示允许的几个携带自定义的头
    Access-Control-Max-Age: 86400
    上面指定了 preflight 请求的结果能够被缓存几秒(s)
    Vary: Accept-Encoding, Origin
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    预检请求完成之后,发送实际请求:

    POST /doc HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    X-PINGOTHER: pingpong
    Content-Type: text/xml; charset=UTF-8
    Referer: https://foo.example/examples/preflightInvocation.html
    Content-Length: 55
    Origin: https://foo.example
    Pragma: no-cache
    Cache-Control: no-cache
    
    Arun
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:40 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: https://foo.example
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 235
    Keep-Alive: timeout=2, max=99
    Connection: Keep-Alive
    Content-Type: text/plain
    
    [Some XML payload]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    其中,xhr对象的withCredentials方法=true时会向服务器发送cookie
    但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者。

    感谢,参考来自MDN

  • 相关阅读:
    Java设计模式 _行为型模式_空对象模式
    调用ros系统摄像头可视化rqt工具
    Hudi源码|bootstrap源码分析总结(写Hudi)
    webpack打包
    G. SlavicG‘s Favorite Problem(树的遍历DFS,BFS均可)
    ThreadLocal在接口参数间传递中的使用
    JAVAEE初阶相关内容第八弹--多线程(初阶)
    3. 文档概述(Documentation Overview)
    人口数据集:地级市常住人口与户籍人口、人口1%抽样调查数据两大维度指标数据
    C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏
  • 原文地址:https://blog.csdn.net/qq_52480906/article/details/126216782