跨域资源共享(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
如需允许所有资源都可以访问您的资源,其语法如下:
Access-Control-Allow-Origin: <origin> | *
-
Access-Control-Allow-Methods
首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。 - 其中,origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
Access-Control-Allow-Headers
首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。 支持与客户端商量好的自定义的header信息.
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
-
Access-Control-Expose-Headers
头让服务器把允许浏览器访问的头放入白名单,例如:
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例子。
Access-Control-Max-Age: <delta-seconds>
-
Access-Control-Allow-Credentials
头指定了当浏览器的credentials
设置为true时是否允许浏览器读取response的内容。当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials
。请注意:简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。
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