最近在做一個項目,前后端分離,不可避免的遇到了跨域問題。起初是配置跨域:
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addExposedHeader("Authorization");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
在測試時發現在spring security下這些跨域配置並沒有生效
需要在springsecurity配置中加上cors()來開啟跨域以及requestMatchers(CorsUtils::isPreFlightRequest).permitAll()來處理跨域請求中的preflight請求。
//開啟跨域 cors()
http.cors().and().csrf().disable().authorizeRequests()
//處理跨域請求中的Preflight請求
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(HttpMethod.GET,"/hello/hello").permitAll()
.antMatchers("/oauth/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
//自定義登錄頁面
.loginPage("/oauth/login")
.and()
.logout()
.and()
.addFilter(new JWTLoginFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager()));
當jwt token無效過期等時請求將跳到你自定義的登錄頁面(默認是/login),基於前后端分離,我這里自定義了一個登陸請求,以restful風格返回給前端,前端可依據返回的code全局路由到真正的登錄頁面。
跨域解決了,然后坑又來了,一堆的/oauth/login請求是什么鬼???陷入死循環了。。。當你的token無效時,他將繼續帶着token請求/oauth/login,在這個請求時,又要開始判斷他的token,反反復復。。。
所以,在token的校驗中,當我們的請求是/oauth/login時,將請求放行
String header = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
String requestURI = request.getRequestURI();
// 如果請求頭中沒有Authorization信息則直接放行了
if(header == null || !header.startsWith(JwtTokenUtils.TOKEN_PREFIX) || requestURI.equals("/oauth/login")){
chain.doFilter(request,response);
return;
}