HTTP访问控制(CORS)

2022-05-17 18:55:24 浏览数 (1)

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

比如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 https://img.yuanmabao.com/zijie/pic/2022/05/17/vmt3ehslroy.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

浏览器

安全限制: 让浏览器禁止检查, 不推荐

XHR请求

jsonp(不推荐使用) 这种方案其实我是不赞同的,第一,在编码上jsonp会单独因为回调的关系,在传入传出还有定义回调函数上都会有编码的”不整洁”.简单阐述jsonp能够跨域是因为javascript的script标签,通过服务器返回script标签的code,使得该代码绕过浏览器跨域的限制。并且在客户端页面按照格式定义了回调函数,使得script标签返回实现调用

  • 服务器需要做改动(当然是自己的服务器, 才能该)
  • 只支持GET方式
  • 发送的不是xhr请求, 这个有新特性.

跨域

被调用方修改是支持跨域

本节列出了可用于发起跨域请求的首部字段。请注意,这些首部字段无须手动设置。 当开发者使用 XMLHttpRequest 对象发起跨域请求时,它们已经被设置就绪。 举例客户端的请求

代码语言:javascript复制
Origin: http://foo.example 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
  • Origin 首部字段表明预检请求或实际请求的源站。

注意,不管是否为跨域请求,ORIGIN 字段总是被发送。

  • Access-Control-Request-Method 首部字段用于预检请求。其作用是,将实际请求所使用的 HTTP 方法告诉服务器。
  • Access-Control-Request-Headers 首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。

在响应头中添加:

代码语言:javascript复制
Access-Control-Allow-Origin: http://foo.example 
Access-Control-Allow-Methods: POST, GET, OPTIONS 
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type 
  • Access-Control-Allow-Origin 如需允许所有资源都可以访问您的资源,其语法如下:
代码语言:javascript复制
Access-Control-Allow-Origin: <origin> | *
  • Access-Control-Allow-Methods 首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。
  • 其中,origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
  • Access-Control-Allow-Headers 首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。 支持与客户端商量好的自定义的header信息.
代码语言:javascript复制
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
  • Access-Control-Expose-Headers 头让服务器把允许浏览器访问的头放入白名单,例如:
代码语言:javascript复制
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

这样浏览器就能够通过getResponseHeader访问X-My-Custom-Header和 X-Another-Custom-Header 响应头了。

  • Access-Control-Max-Age 头指定了preflight请求的结果能够被缓存多久,请参考本文在前面提到的preflight例子。
代码语言:javascript复制
Access-Control-Max-Age: <delta-seconds>
  • Access-Control-Allow-Credentials 头指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials。请注意:简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。
代码语言:javascript复制
Access-Control-Allow-Credentials: true

spring 应用服务器的实现:

自定义filter实现, 其实还是根据要求, 放置符合条件的请求头.

服务器端的实现: nginx / apache

只列举nginx的实现

代码语言:javascript复制
server {
    listen       9000;
    server_name  localhost;

    location / {
        proxy_pass http://localhost/;

        #这里最好做判断,怕麻烦的话就写*,但是不建议
        if ($http_origin = http://localhost){
            add_header Access-Control-Allow-Origin http://localhost;
        }
        #支持其他请求
        add_header Access-Control-Allow-Methods *;
        
        #为了方便,这样写了
        add_header Access-Control-Allow-Headers $http_access_control_request_headers;
    }
}
调用方修改是隐藏跨域

反向代理(推荐使用) 代理访问其实在实际应用中有很多场景,在跨域中应用的原理做法为:通过反向代理服务器监听同端口,同域名的访问,不同路径映射到不同的地址,比如,在nginx服务器中,监听同一个域名和端口,不同路径转发到客户端和服务器,把不同端口和域名的限制通过反向代理,来解决跨域的问题,案例如下:

带cookie的跨域

小知识, 详见参考

参考

HTTP访问控制(CORS) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

nginx解决跨域问题 - 个人文章 - SegmentFault 思否 https://segmentfault.com/a/1190000019227927?utm_source=tag-newest

JS中的跨域问题及解决办法汇总_lareinalove的博客-CSDN博客 https://blog.csdn.net/lareinalove/article/details/84107476

0 人点赞