CORS跨域请求出现问题

本文涉及的产品
.cn 域名,1个 12个月
简介: 1、问题描述Access to XMLHttpRequest at ‘http://localhost:8080/user/register’ from origin ‘http://localhost:8002’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcar

1、问题描述

Access to XMLHttpRequest at ‘http://localhost:8080/user/register’ from origin ‘http://localhost:8002’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

具体情况为前后端分离项目,后端在控制器上已经加上了@CrossOrigin注解,但前端请求后端接口时仍出现跨域问题

2、问题追溯

前端代码:

this.$http({
  url: this.$http.adornUrl('/user/register'),
  method: 'post',
  headers:{
    "Content-Type": 'application/json;charset=utf-8', // 解决415问题
  },
  data: JSON.stringify(params)
}).then()

axios配置:

const http = axios.create({
  timeout: 1000 * 30,
  withCredentials: true, // 当前请求为跨域类型时是否在请求中协带cookie
})

后台代码:

@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService iUserService;
    @PostMapping("register")
    public Result register(@RequestBody UserBody userBody) {
        return iUserService.register(userBody);
    }
}


由于前端form表单默认的传参方式为application/x-www-form-urlencoded,所以请求后端接口时会出现Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported这样一个数据请求 contentType 与后端不一致的415错误


所以我在前端请求中设置了"Content-Type": 'application/json;charset=utf-8'这样一个请求头以解决这个错误


tips:加上这个请求头便使得了这个请求变为复杂请求(详见下)


options 请求就是预检请求,可用于检测服务器允许的 http 方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求。


这是在跨域情况下,浏览器发起"复杂请求"时主动发起的。跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。


某些请求不会触发CORS预检请求,这样的请求一般称为 “简单请求” ,而会触发预检的请求则是 “复杂请求” 。


简单请求

请求方式为GET、HEAD、POST时的请求;

认为设置规范集合之内的首部字段,如Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width;

Content-Type 的值仅限于下列三者之一,即application/x-www-form-urlencoded、multipart/form-data、text/plain;

请求中的任意 XMLHttpRequestUpload对象均没有注册任何事件监听器;

请求中没有使用 ReadableStream对象

复杂请求

PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH;

人为设置了以下集合之外首部字段,即简单请求外的字段;

Content-Type 的值不属于下列之一,即application/x-www-form-urlencoded、multipart/form-data、text/plain。

然而解决了415问题之后,请求还是失败,这回变成了CORS错误,便是开篇所展示的错误


查阅资料后发现CORS请求默认不发送Cookie和HTTP认证信息,如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段,另一方面,开发者必须在AJAX请求中打开withCredentials属性。否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。显然在请求中携带cookie显然是很常见的操作,所以我在axios设置中开启了withCredentials设置


问题就出现在这里了如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名


这也就是页面控制台错误信息中所表达的意思

3、总结归纳

当前端配置withCredentials=true时, 后端配置Access-Control-Allow-Origin不能为*, 必须是相应地址

当配置withCredentials=true时, 后端需配置Access-Control-Allow-Credentials

当前端配置请求头时, 后端需要配置Access-Control-Allow-Headers为对应的请求头集合

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

即=》如果跨域需要携带cookie去请求,Access-Control-Allow-Credentials必须为true,但是需要注意当Access-Control-Allow-Credentials=true时,Access-Control-Allow-Origin就不能为” * “ ,必须是明确的域名

后端需要返回的Header有哪些?

# 服务端允许访问的域名
Access-Control-Allow-Origin=https://idss-uat.jiuyescm.com
# 服务端允许访问Http Method
Access-Control-Allow-Methods=GET, POST, PUT, DELETE, PATCH, OPTIONS
# 服务端接受跨域带过来的Cookie,当为true时,origin必须是明确的域名不能使用*
Access-Control-Allow-Credentials=true
# Access-Control-Allow-Headers 表明它允许跨域请求包含content-type头
Access-Control-Allow-Headers=Content-Type,Accept
# 跨域请求中预检请求(Http Method为Option)的有效期,20天,单位秒
Access-Control-Max-Age=1728000

4、封装为配置类

@Configuration
public class WebConfig implements WebMvcConfigurer {
    // 拦截器跨域配置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        /*
            // 跨域路径
            CorsRegistration cors = registry.addMapping("/**");
            // 可访问的外部域
            cors.allowedOrigins("http://localhost:8002");
            // 支持跨域用户凭证
            cors.allowCredentials(true);
            cors.allowedOriginPatterns("*");
            // 设置header能携带的信息
            cors.allowedHeaders("*");
            // 设置支持跨域的请求方法
            cors.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTION");
            // 设置跨域过期时间
            cors.maxAge(3600);
        */
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8002")
                .allowCredentials(true)
                .allowedOriginPatterns("*")
                .allowedHeaders("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTION")
                .maxAge(3600);
    }
}

相关文章
|
6月前
|
移动开发 JSON 前端开发
跨域资源共享(CORS):详解跨域请求的限制与解决方法
跨域资源共享(CORS):详解跨域请求的限制与解决方法
|
3月前
|
JSON 小程序 API
【Azure API 管理】APIM CORS策略设置后,跨域请求成功和失败的Header对比实验
【Azure API 管理】APIM CORS策略设置后,跨域请求成功和失败的Header对比实验
|
6月前
|
JavaScript 安全 前端开发
js开发:请解释什么是跨域请求(CORS),以及如何解决跨域问题。
CORS是一种W3C标准,用于解决浏览器同源策略导致的跨域数据访问限制。它通过服务器在HTTP响应头添加标志允许特定源进行跨域请求。简单请求无需预检,而预检请求(OPTIONS)用于询问服务器是否接受非简单请求。服务器端配置响应头如`Access-Control-Allow-Origin`等实现CORS策略,客户端JavaScript则正常发起请求。若配置不当,浏览器将阻止跨域访问,保障安全。
84 2
|
JSON JavaScript 前端开发
如何处理跨域请求:JSONP、CORS 和代理服务器
处理跨域请求是前端开发中的常见挑战,因为浏览器的同源策略限制了在不同域名、协议或端口之间进行直接通信。为了解决跨域请求的问题,可以使用以下三种常见的方法:JSONP、CORS和代理服务器。
453 0
|
前端开发 Java
SpringBoot开发秘籍 - 处理跨域请求CORS
SpringBoot开发秘籍 - 处理跨域请求CORS
87 0
|
Python
Python编程:flask-cors模块解决Flask跨域请求Cross-Origin问题
Python编程:flask-cors模块解决Flask跨域请求Cross-Origin问题
445 0
|
Web App开发 缓存 JSON
Cors跨域(一):深入理解跨域请求概念及其根因(下)
Cors跨域(一):深入理解跨域请求概念及其根因(下)
Cors跨域(一):深入理解跨域请求概念及其根因(下)
|
缓存 前端开发 JavaScript
Cors跨域(一):深入理解跨域请求概念及其根因(上)
Cors跨域(一):深入理解跨域请求概念及其根因(上)
Cors跨域(一):深入理解跨域请求概念及其根因(上)
|
前端开发 Java 程序员
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(下)
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(下)
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(下)
|
前端开发 Java Spring
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(中)
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(中)
CORS跨域资源共享(三):@CrossOrigin/CorsFilter处理跨域请求示例及原理分析【享学Spring MVC】(中)