CORS 跨域一篇文章就够了!Spring + Spring Security 配置!!

3 篇文章 0 订阅

目录

一、跨域

二、什么是 CORS

2.1 简单请求

2.2 非简单请求

三、Spring 跨域解决方案

四、Spring Security 跨域解决方案

4.1 原理分析     

4.1 解决方案

4.3 源码分析



一、跨域

        跨域问题是实际应用开发中一个非常常见的需求,在 Spring 框架中对于跨域问题的处理方案有好几种,引入了 Spring Security 之后,跨域问题的处理方案又增加了。

        就不能在基于 传统的解决去解决跨域问题,因为默认的都会 Spring Security 的认证Filter 所拦截从而导致失效,因为 Spring 的三种解决方案两种是通过 Interceptor 拦截器而解决,而Spring Security 的 Filter 是在 Interceptor 拦截器前执行,及时是是通过 Spring 的 CorfFilter ,但是如果是没能在 Spring Security的 Filter 前执行也会导致失效。

二、什么是 CORS

        

        CORS (Cross-Origin Resource Sharing ) 是由 W3C 制定的一种跨域资源共享技术标准,其目的就是为了解决前端的跨域请求。在 JavaEE 开发中,最常见的前端跨域请求解决方案是早期的 JSONP,但是 JSONP 只支持 GET 请求,这是一个很大的缺陷,而 CORS 则支持多种 HTTP 请求方法,也是目前主流的跨域解决方案 。

        CORS 中新增了一组 HTTP 请求头字段,通过这些字段,服务器告诉浏览器,哪些网站通过浏览器有权限访问哪些资源。同时规定,对哪些可能修改服务器数据的 HTTP 请求方法(如 GET 以外的 HTTP 请求等),浏览器必现首先使用 OPTIONS 方法发起一个预检请求 (prenightst),预检请求的目的是查看服务端是否支持即将发起的跨域请求,如果服务端允许,才发送实际的 HTTP 请求 。在预检请求的返回中,服务器端也可通知客户端,是否需要携带身份凭证 (如 Cookie 、HTTP 认证信息等) 。

CORS :同源/同域 = 协议 + 主机 + 端口

2.1 简单请求

  GET 请求为例,如果需要发起一个跨域请求,则请求头如下:        

Host: localhost:8080 
Origin: http://localhost:8081 
Referer: http://localhost:8081/index.html

如果服务端支持该跨域请求,那么返回的响应头中将包含如下字段:

# 告知浏览器对该域的请求是允许跨域的
Access-Control-Allow-Origin:http://localhost: 8081 

        Access-Control-Allow-Origin 字段用来告诉浏览器可以访问该资源的域,当浏览器收到这样的响应头信息之后,提取出 Access-Control-Allow-Origin 字段中的值,发现该值包含当前页面所在的域,就知道这个跨域是被允许的,因此就不再对前端的跨域请求进行限制。这属于简单请求,既不需要进行预检请求的跨域。

2.2 非简单请求

         对于一些非简单请求,会首发发送一个预检请求。预检请求类似下面这样:

OPTIONS /put HTTP/1.1   # 请求方式 和类型
Host: localhost:8080 # 请求的地址 
Connection: keep-alive  # 连接状态
Accept: */*   # 允许的响应类型 
Access-Control-Request-Method:PUT  # 当前方法的请求方法
Origin: http://localhost: 8081   # 跨域请求的url 
Referer:http://localhost:8081/index.html  # 跨域的地址       

        请求方法是 OPTIONS ,请求头 Origin 就告诉服务端当前页面所在域,请求头 Access-Control-Request-Methods 告诉服务端即将发起的跨域请求所使用的方法。服务端对此进行判断,如果允许即将发起的跨域请求,则会给出如下响应:

HTTP/1.1 200 # 当前请求装填 
Access-Control-Allow-Origin: htpp://localhost:8081  #浏览器允许跨域地址
Access-Control-Request-Methods:PUT # 请求方式 
Access-Control-Max-Age:3600 # 预检请求的有效期

        Access-Control-Allow-Methods 字段表示允许跨域方法:Access-Control-Max-Age 字段表示预检请求的有效期,单位为秒,在有效期内如果发起该跨域请求,则不用再次发起预检请求。预检请求结束后,接下来就会发起一个真正的跨域请求,跨域请求和前面的简单请求跨域步骤类似。

三、Spring 跨域解决方案

spring 跨域 Cors 解决方案_千城丶Y的博客-CSDN博客

四、Spring Security 跨域解决方案

4.1 原理分析     

        当我们为项目添加了 Spring Security 依赖之后,发现上面三种跨域方式有的失效了,有的则可以继续使用,这是怎么回事?

        通过 @CrossOrigin 注解或者重写 addCorsMappings 方法配置跨域,统统失效了,通过CorsFilter 配置的跨域,有没有失效则要看过滤器的优先级,如果过滤器优先级高于 Spring Security 过滤器,即限于 Spring Security 过滤器执行,则 CorsFilter 所配置的跨域处理依然有效,如果过滤器优先级低于 Spring Security 过滤器,则 CorsFilter 所配置的跨域处理就会失效。

        为了理清楚这个问题,我们先简单了解一下 Filter 、DispatcherServlet 以及 Interceptor 执行顺序。

        理清楚了执行顺序,我们再来看跨域请求过程。由于非简单请求要首先发送一个预检请求 request ,而预检请求并不会携带认证信息,所以预检请求就有被 Spring Security 拦截的可能。因此通过 @CrossOrigin 注解或者重写addCorsMappings 方法配置跨域就会失效。如果使用 CorsFilter 配置的跨域,只要过滤器优先级高于 Spring Security 过滤器就不会有问题,反之同样出现问题。

4.1 解决方案

        Spring Secuirty 中提供了更专业的方式来解决预检请求所面临的问题。

        Spring Security 的解决方案是基于 SpringMvc 的 CorsFilter 实现的,也就是将CorsFilter的配置交给我们,而具体CorsFilter 类的创建交给 Spring Security 进行处理。

如:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * web安全配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .cors().configurationSource(corsConfiguration()); // 配置 CorsFilter 配置信息
    }

    /**
     * Cors 的配置信息 配置+路径
     */
    CorsConfigurationSource corsConfiguration (){
        // Cors配置类
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(false); // 是否返回时生成凭证
        corsConfiguration.setAllowedHeaders(Arrays.asList("*")); // 允许请求携带哪些请求头信息
        corsConfiguration.setAllowedMethods(Arrays.asList("*")); // 允许哪些类型的请求方法
        corsConfiguration.setAllowedOrigins(Arrays.asList("*")); // 允许哪些域可以进行方法
        corsConfiguration.setMaxAge(3600L); // 设置预检的最大的时长
        corsConfiguration.setExposedHeaders(Collections.emptyList()); // 设置返回暴露的响应头信息

        // 设置注册URL 配置类
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource() ;
        source.registerCorsConfiguration("/**",corsConfiguration);

        return source;
    }
}

4.3 源码分析

        底层还是通过CorsFilter 处理 ,生成配置 CorsFilter 是交给 CorsConfigurer进行处理的。

结论:

        Spring Security 底层也是使用 CorsFilter ,而这个Filter 执行顺序就至关重要,Spring Security 底层帮我我们进行排序,在其他的Filter 前执行就可以正常执行解决跨域问题了。

1.获取CorsFilter 添加到Spring Security Filter china 中

2.添加方法

477791794ab20e26b9b66feda040c826.png3.添加后的顺序

65c421e8d1d6443047957bd96ff21519.png4.Filter排序

be3256a94a946e92c4a8f8d8b1bc8a99.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值