Spring Security下解决跨域问题

前言:今天在写项目的时候碰到了跨域问题,在网站找了各种解决办法,大部分都是添加@CrossOrigin注解或者添加配置类,但我花了整整一天还是没能解决问题。后来实在是不行,便想起了官网文档。结果还真的找到了解决办法!!!而且官方文档中还指明了原因!!看来以后遇到bug先要查查官网。

参考官方文档:https://docs.spring.io/spring-security/site/docs/5.4.2/reference/html5/#jc

问题描述

image-20210210225641737

原因

Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.

由上文可知,当使用Spring Security时,一定要在Spring Security认证前解决跨域问题。因为在跨域的场景下,浏览器在发送真实请求前会先发送一个预请求(简单请求不会发送)。预请求的请求方法是OPTIONS,没有携带数据,目的是测试从浏览器到服务器通不通。如果请求成功,就证明从浏览器到服务器通,那么浏览器就会发送真实的请求。

image-20210210225957566

image-20210210230037728

如果服务器没有在Spring Security之前处理掉预请求,那么在用户进行登录操作时,Spring Security就会对预请求进行拦截。因为预请求不携带数据(token、session等),因此Spring Security便无法为其进行认证与授权,而是直接拒绝服务。这也就导致用户无法登录。

解决

官网里面给出了解决方法,不需要使用@CrossOrigin,只需要简单的配置就可以,以下是官网给出的配置:

Java配置类:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors(withDefaults())
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

或者XML的方式:

<http>
    <cors configuration-source-ref="corsSource"/>
    ...
</http>
<b:bean id="corsSource" class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
    ...
</b:bean>

我才用的是配置类的方式。官网给出的方法用着有些别扭,我进行了一些调整,但功能相同:

    @Override
    protected void configure(HttpSecurity http) throws Exception {



        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint())
                .and().csrf().disable()
                // by default uses a Bean by the name of corsConfigurationSource
                .cors(withDefaults())//一定不要忘
                .authorizeRequests()
                .anyRequest().authenticated()
//                需要自定义配置,退出请求地址
                .and().logout().logoutUrl("/examination/user/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();
    }


	@Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        configuration.setAllowCredentials(true);
        configuration.addAllowedOrigin("http://主机:端口号");
        configuration.addAllowedHeader(CorsConfiguration.ALL);
        configuration.addAllowedMethod(CorsConfiguration.ALL);
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

配置完重启项目,大功告成!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值