SpringBoot解决CORS跨域请求

1、同源策略(Same Origin Policy):

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。 同源策略是浏览器安全的基石。

2、跨源资源共享(Cross-Origin Resource Sharing)

为了解决浏览器同源问题,W3C 提出了跨源资源共享,即 CORS。CORS就是为了解决SOP问题而生的。当然还有其他解决SOP的方案。

浏览器将CORS请求分为两类:简单请求(simple request)和非简单请求/预检请求(not-so-simple request)。

参考这个两篇博主的文章,简单易通:

axios请求接口发起两次请求(OPTIONS 与POST/GET)

SpringBoot配置Cors解决跨域请求问题

更详细的 CORS和HTTP知识,参考:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

 

解决CORS跨域方式有三种。如果在项目开发中,发现每次发起请求都是两条,一次OPTIONS请求,一次正常请求。那就需要配置Access-Control-Max-Age,避免每次都发出预检请求。

一、@CrossOrigin 注解

使用@CrossOrigin 注解实现,针对的是某一接口或者对一系列接口添加 CORS 配置。

1、对某一接口添加 CORS配置,可以在方法上添加 @CrossOrigin注解 :

    @CrossOrigin(origins = "http://127.0.0.1:8081")
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "hello";
    }

2、对一系列接口添加 CORS配置,可以在类上添加@CrossOrigin注解,对该类声明所有接口都有效:

 

@Controller
@RequestMapping("/cors")
@CrossOrigin(origins = "http://127.0.0.1:8081")
public class CorsControlller {

    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "hello";
    }
}

那个类需要就在那个类上添加@CrossOrigin注解,如果想添加全局 CORS配置,使用下面两种方式。

二、配置类

WebMvcConfigurerAdapter 在Spring5.0中已经标记为@deprecated过时的。我们直接使用WebMvcConfigurer。

1、Access-Control-Allow-Origin

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

2、Access-Control-Allow-Methods

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

3、Access-Control-Expose-Headers

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

4、Access-Control-Allow-Credentials

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

5、Access-Control-Max-Age

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

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

三、基于过滤器的方式

添加 Filter 的方式,配置 CORS 规则,简单明了,就是在response中写入这些响应头。

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, xxxToken");
        filterChain.doFilter(servletRequest, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

 

四、原理剖析

1、CorsConfiguration类

无论是通过哪种方式配置 CORS,其实都是在构造 CorsConfiguration类。 一个 CORS 配置用一个 CorsConfiguration类来表示,它的定义如下:

2、DefaultCorsProcessor类

Spring 中对 CORS 规则的校验,都是通过委托给 DefaultCorsProcessor实现的。

DefaultCorsProcessor 处理过程如下:

  1. 判断依据是 Header中是否包含 Origin。如果包含则说明为 CORS请求,转到 2;否则,说明不是 CORS 请求,不作任何处理。
  2. 判断 response 的 Header 是否已经包含 Access-Control-Allow-Origin,如果包含,证明已经被处理过了, 转到 3,否则不再处理。
  3. 判断是否同源,如果是则转交给负责该请求的类处理
  4. 是否配置了 CORS 规则,如果没有配置,且是预检请求,则拒绝该请求,如果没有配置,且不是预检请求,则交给负责该请求的类处理。如果配置了,则对该请求进行校验。

校验就是根据 CorsConfiguration 这个类的配置进行判断:

  1. 判断 origin 是否合法
  2. 判断 method 是否合法
  3. 判断 header是否合法
  4. 如果全部合法,则在 response header中添加响应的字段,并交给负责该请求的类处理,如果不合法,则拒绝该请求。

 

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值