首頁  >  文章  >  Java  >  SpringBoot+Spring Security無法實現跨域怎麼解決

SpringBoot+Spring Security無法實現跨域怎麼解決

WBOY
WBOY轉載
2023-05-16 15:40:551085瀏覽

SpringBoot Spring Security無法實現跨域

未使用Security時跨域:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
@AutoConfigureBefore(SecurityConfig.class)
public class MyMvcConfigurer implements WebMvcConfigurer {
    public void addCorsMappings(CorsRegistry registry){
        LOGGER.info("跨域已设置");
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

整合Security時發現只用上述方法前後端分離時仍存在跨域問題,

解決方法如下:

@Configuration
@AutoConfigureBefore(Swagger2Configuration.class)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginProcessingUrl("/user/login")
                .loginPage("/singIn.html")
                .successHandler(moyuAuthenticationSuccessHandler)
                .failureHandler(moyuAuthenticationFailureHandler)
                .and()
                .apply(moyuSocialSecurityConfig)
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(3600*24*7)
                .userDetailsService(userDetailsService)
                .and()
                .authorizeRequests()
                .antMatchers("/user/login","/login","/singIn.html","**","/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .cors()
                .and()
                .csrf().disable();
    }
}

重點加入程式碼:

   .and()
   .cors()//新加入
   .and()
   .csrf().disable();

引用Spring Security 專案的跨域處理

最近專案採用了前後端分離的框架,前端和後台介面沒有部署到一個站點,出現了跨域問題,什麼是跨域,這裡就不再贅述,直接說解決方法。

Spring 解決跨域的方式有很多,個人採用了Crosfilter的方式

具體代碼如下:

@Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new      UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }

配置完成後,測試調用,報錯401,依然不行。網上查資料得知,跨域請求會進行兩次。具體流程請見下圖:

SpringBoot+Spring Security无法实现跨域怎么解决

每次跨網域請求,真正請求到達後端之前,瀏覽器會先發起一個preflight request,請求方式為OPTIONS 詢問服務端是否接受該跨域請求,具體參數如下圖:

SpringBoot+Spring Security无法实现跨域怎么解决

但是該請求不能攜帶cookie和自己定義的header。

由於專案中引入了Spring security ,而我使用的token傳遞方式是在header中使用authorization 欄位,這樣依賴Spring Security攔截到preflight request 發現它沒有攜帶token,就會報錯401,沒有授權。

解決這個問題很簡單,可以使用以下設定

讓Spring security 不校驗preflight request 。

 @Override
    public void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry 
        = http.authorizeRequests();
        registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll();//让Spring security放行所有preflight request 
    }

再試就搞定了,但是後端直接配置支援跨域會導致兩次請求。也使用另一種方​​式,使用Nginx 轉送請求也可以。

以上是SpringBoot+Spring Security無法實現跨域怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除