SpringBoot+Spring Security無法實現(xiàn)跨域的解決方案
SpringBoot+Spring Security無法實現(xiàn)跨域
未使用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("跨域已設(shè)置");
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
整合Security時發(fā)現(xiàn)只用上述方法前后端分離時仍存在跨域問題,
解決方法如下:
@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 項目的跨域處理
最近項目采用了前后端分離的框架,前端和后臺接口沒有部署到一個站點,出現(xiàn)了跨域問題,什么是跨域,這里就不再贅述,直接說解決辦法。
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);
}
配置完成后,測試調(diào)用,報錯401,依然不行。網(wǎng)上查資料得知,跨域請求會進行兩次。具體流程見下圖:

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

但是該請求不能攜帶cookie和自己定義的header。
由于項目中引入了Spring security ,而我使用的token傳遞方式是在header中使用authorization 字段,這樣依賴Spring Security攔截到 preflight request 發(fā)現(xiàn)它沒有攜帶token,就會報錯401,沒有授權(quán)。
解決這個問題很簡單,可以使用以下配置
讓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 轉(zhuǎn)發(fā)一下請求也可以。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
screw?Maven插件方式運行時在編譯打包時跳過執(zhí)行的問題解決方法
這篇文章主要介紹了screw?Maven插件方式運行時在編譯打包時跳過執(zhí)行的問題解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03
java 實現(xiàn)字節(jié)流和字節(jié)緩沖流讀寫文件時間對比
這篇文章主要介紹了java 實現(xiàn)字節(jié)流和字節(jié)緩沖流讀寫文件時間對比,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
mybatis中${}和#{}的區(qū)別以及底層原理分析
這篇文章主要介紹了mybatis中${}和#{}的區(qū)別以及底層原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
springboot整合shiro登錄失敗次數(shù)限制功能的實現(xiàn)代碼
這篇文章主要介紹了springboot整合shiro-登錄失敗次數(shù)限制功能,實現(xiàn)此功能如果是防止壞人多次嘗試,破解密碼的情況,所以要限制用戶登錄嘗試次數(shù),需要的朋友可以參考下2018-09-09
SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢
這篇文章主要為大家詳細介紹了SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05

