SpringBoot+Spring Security無法實(shí)現(xiàn)跨域的解決方案
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時(shí)發(fā)現(xiàn)只用上述方法前后端分離時(shí)仍存在跨域問題,
解決方法如下:@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(); }}重點(diǎn)加入代碼:
.and() .cors()//新加入 .and() .csrf().disable();引用Spring Security 項(xiàng)目的跨域處理
最近項(xiàng)目采用了前后端分離的框架,前端和后臺接口沒有部署到一個(gè)站點(diǎn),出現(xiàn)了跨域問題,什么是跨域,這里就不再贅述,直接說解決辦法。
Spring 解決跨域的方式有很多,個(gè)人采用了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)用,報(bào)錯(cuò)401,依然不行。網(wǎng)上查資料得知,跨域請求會進(jìn)行兩次。具體流程見下圖:
每次跨域請求,真正請求到達(dá)后端之前,瀏覽器都會先發(fā)起一個(gè)preflight request,請求方式為OPTIONS 詢問服務(wù)端是否接受該跨域請求,具體參數(shù)如下圖:
但是該請求不能攜帶cookie和自己定義的header。
由于項(xiàng)目中引入了Spring security ,而我使用的token傳遞方式是在header中使用authorization 字段,這樣依賴Spring Security攔截到 preflight request 發(fā)現(xiàn)它沒有攜帶token,就會報(bào)錯(cuò)401,沒有授權(quán)。
解決這個(gè)問題很簡單,可以使用以下配置讓Spring security 不校驗(yàn)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 }
再試就搞定了,但是后端直接配置支持跨域會導(dǎo)致兩次請求。還使用另一種方式,使用Nginx 轉(zhuǎn)發(fā)一下請求也可以。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. 基于PHP做個(gè)圖片防盜鏈2. .NET中實(shí)現(xiàn)對象數(shù)據(jù)映射示例詳解3. 如何使用ASP.NET Core 配置文件4. jscript與vbscript 操作XML元素屬性的代碼5. php使用正則驗(yàn)證密碼字段的復(fù)雜強(qiáng)度原理詳細(xì)講解 原創(chuàng)6. ASP.NET MVC使用Boostrap實(shí)現(xiàn)產(chǎn)品展示、查詢、排序、分頁7. asp.net core 認(rèn)證和授權(quán)實(shí)例詳解8. uni-app結(jié)合.NET 7實(shí)現(xiàn)微信小程序訂閱消息推送9. XML在語音合成中的應(yīng)用10. 基于javaweb+jsp實(shí)現(xiàn)企業(yè)車輛管理系統(tǒng)
