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;
    }

配置完重啟項目,大功告成!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM