1、在启动类中继承WebMvcConfigurerAdapter,重写其中的addCorsMappings方法

package com.example.springbootdemo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@SpringBootApplication
public class SpringbootdemoApplication extends WebMvcConfigurerAdapter {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootdemoApplication.class, args);
    }
    @Override
    public void addCorsMappings(CorsRegistry registry) {
 
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedOrigins("*")
                .allowedMethods("*");
    }
}

2、在允许跨域请求的controller中使用@CrossOrigin 注解

import org.springframework.web.bind.annotation.CrossOrigin;
@CrossOrigin
@RestController
public class HelloWorldController {
/**
*
*
*/
}

Access-Control-Allow-Origin 

response.setHeader("Access-Control-Allow-Origin", "*"); //设置允许任何域名跨域访问

response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080/");//设置指定域访问


Access-Control-Allow-Credentials


Access-Control-Allow-Credentials 这个是服务端下发到客户端的 response 中头部字段,意义是允许客户端携带验证信息,例如 cookie 之类的,我们的客户端和服务端交互的时候使用的是 token,通过 Authorization头发送到服务端

Access-Control-Allow-Headers

当浏览器发送接口请求出现跨域问题时,目前的做法通常会在接口服务器增加如下配置。

Access-Control-Allow-Origin: *
复制代码

但是有时也会出现 Access-Control-Allow-Headers 的错误问题。

Access to XMLHttpRequest at 'http://www.xxx.com/api' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
复制代码

下面我们就来分析一下原因和解决办法。

原因

浏览器在发送跨域请求并且包含自定义 header 字段时,浏览器会先向服务器发送 OPTIONS 预检请求(preflight request),探测该请求服务是否允许自定义跨域字段。

如果允许,则继续执行 POST、GET请求,否则返回提示错误。

OPTIONS 请求:

Request URL:http://xxx.com/api  
Request Method:OPTIONS  
Status Code:200 OK  
Remote Address:00.00.00.00:80  
Referrer Policy:no-referrer-when-downgrade 
复制代码

Request Header:

Accept:*/*  
Accept-Encoding:gzip, deflate  
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8  
Access-Control-Request-Headers:content-type,xfilecategory,xfilename,xfilesize  
Access-Control-Request-Method:GET  
Connection:keep-alive  
Host:http://localhost:8080/  
Origin:http://localhost:8080/  
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
复制代码

注意⚠️

此时浏览器会向服务器发送预检请求,询问是否支持跨域的自定义 header 字段。设置的 Access-Control-Request-Headers 服务器需要适当的作出应答。

服务器应答方式

服务器需要对 OPTIONS 请求作出应答,通过设置 header 包含 Access-Control-Request-Headers,并且包含 OPTIONS 请求中的 Access-Control-Request-Headers 对值。

例如:

response.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token");
复制代码

另外(其实很重要)

如果你对请求是 simple headers 方式则不会发送预检请求。

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type

当仅包含以上这些请求头(以及满足下面列出的附加要求的值)时,请求不需要在 CORS 的上下文中发送预检请求。

附加要求

CORS 安全标头还必须满足以下要求才能成为 CORS 安全的请求标头:

  • 对于 Accept-LanguageContent-Language:只能存在值 0-9A-Za-z,空间或 *,=.;=
  • 关于 AcceptContent-Type:不能包含 CORS 不安全的请求头字节:"():<>?@[\]{}DeleteTab 和控制字符:0x000x19
  • Content-Type:需要有一个 MIME 类型的值(忽略参数)。可以是 application/x-www-form-urlencodedmultipart/form-datatext/plain 的任意一个。
  • 对于任何 header:值的长度不能大于 128。

通常影响程序发送预检请求的总是 Content-Type 的设置。如果我们在跨域请求时不需要发送预检请求,那么可以通过设置浏览器请求 Content-Typeapplication/x-www-form-urlencodedmultipart/form-datatext/plain 的任意一个来避免。

例如:

headers.set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

Access-Control-Allow-Methods 

Access-Control-Request-Method是浏览器在CORS预检请求中设置的请求标头,它只能有一个值.所述Access-Control-Allow-Methods报头是CORS响应报头,并且它可以具有多个值.我假设你问的是Access-Control-Allow-Methods因为这是服务器指定的值.

Access-Control-Allow-Methods报头指示该HTTP方法允许对跨域请求特定端点.如果您允许所有HTTP方法,那么可以将值设置为类似的值Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD.但是,如果要将端点限制为仅限几种方法,则应仅包括这些方法.

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐