解决CORS跨域问题:No 'Access-Control-Allow-Origin' header is present on the requested resource

mac2024-03-27  28

前言:首先了解什么是CORS跨域,再来解决问题,会让你更加深入的理解,参考我的另一篇博客:

浅谈CORS跨域https://blog.csdn.net/qq_37896194/article/details/102834574

一、本人遇到的问题

浏览器network请求与响应

        如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。  

        如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://192.168.2.170:8000 Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8  浏览器控制台输出:

        Access to XMLHttpRequest at 'http://192.168.2.170:8000/external/statistics/function' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

        说明Origin指定的域名不在许可范围内,需要在前端和后端添加允许跨域访问的配置


二、本人正确的配置

// 跨域访问配置 private CorsConfiguration buildConfig(){ CorsConfiguration corsConfiguration = new CorsConfiguration(); // 1 设置访问源地址 String[] filter_url = Common.filter_uri; for(int i=0;i<filter_url.length;i++){ corsConfiguration.addAllowedOrigin(filter_url[i]); } // 2 设置访问源请求头 corsConfiguration.addAllowedHeader("*"); corsConfiguration.setAllowCredentials(true); // 3 设置访问源请求方法 corsConfiguration.addAllowedMethod("*"); return corsConfiguration; } @Bean public CorsFilter corsFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); //4 对接口配置跨域设置 “*”代表全部。”**”代表适配所有接口。 source.registerCorsConfiguration("/**",buildConfig()); return new CorsFilter(source); } /** * 过滤url白名单 * http://qntrade.puyunsoft.com //插件pc端域名 * http://item.puyunsoft.com //移动端域名 * http://www.puyunsoft.com //网站 */ public static String[] filter_uri = new String[]{ "http://127.0.0.1:9000", "http://192.168.2.124:3000", "http://192.168.2.170:8000" }; /** * 设置响应头 * @param response */ public static void setResponseHeader(HttpServletResponse response){ // 指定允许其他域名访问 response.setHeader("Access-Control-Allow-Origin","*"); // 响应类型 response.setHeader("Access-Control-Allow-Methods","POST"); // 响应头设置 response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type"); }

另外,前端开发者必须在AJAX请求中打开withCredentials属性: 

var xhr = new XMLHttpRequest();xhr.withCredentials = true;

也可以采用注解方式进行配置跨域参数实现全局跨域

@CrossOrigin(origins = "*",allowCredentials="true",allowedHeaders = "*",methods = {POST,GET})


三、相关配置解释:

 Access-Control-Allow-Origin

        该字段必填。它的值要么是请求时Origin字段的具体值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Methods

        该字段必填。它的值是逗号分隔的一个具体的字符串或者*,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

Access-Control-Expose-Headers

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

 Access-Control-Allow-Credentials

        该字段可选。它的值是一个布尔值,表示是否允许发送Cookie.默认情况下,不发生Cookie,即:false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true。如果服务器不要浏览器发送Cookie,删除该字段即可。

Access-Control-Max-Age

        该字段可选,用来指定本次预检请求的有效期,单位为秒。在有效期间,不用发出另一条预检请求。

        注意:CORS请求发送Cookie时,Access-Control-Allow-Origin只能是与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。


 

最新回复(0)