前言
今天在完成一个接口开发时,发现前端发送的OPTIONS请求一直报403错误,花了2个小时的时间才找到问题的根源。泪目~~~
解决方案
问题其实很简单,springSecurity中,有两中跳过验证的方式,一种使用WebSecurity中的ignoring(),一种时用HttpSecurity中的permitAll()。两中方式虽然都能实现绕Security的过验,但方式却不一样,ignoring方式,会绕过security中所有的过滤器,即连过滤器都不进,也可以理解为不会与security有交集,而permitAll则是会进入security的过滤器,但是一路放行。
虽然效果类似,表面上都放行了,当时今天的坑就和它有关,如果将OPTIONS相关请求放到ignoring中,那么在security中配置cors将会失效,这时就会报403-跨域请求错误,此时有一种解决方式,就是在SpringMVC中配置跨域相关的配置,将跨域相关的验证交由springMVC来管理。但是我不想这么做。
此时就可以使用第二种方式,就将ignorig中OPTIONS相关的url放到httpSecurity中配置,即使用permitAll()进行放行。
代码示例
第一种解决方案(未采用,但能用):
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.cors().configurationSource(configurationSource())
.and()
.formLogin().loginProcessingUrl("/admin/login").permitAll()
.successHandler(new AdminAuthenticationSuccessHandler())
.failureHandler(new AdminAuthenticationFailureHandler())
.and()
.sessionManagement()
.maximumSessions(1)
.expiredSessionStrategy(new AdminSessionInformationExpiredStrategy());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/subsystem/**");
}
CorsConfigurationSource configurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("http://localhost:8080");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
url.registerCorsConfiguration("/**",corsConfiguration);
return url;
}
// 在springMVC中配置cors
@Bean
public CorsFilter corsFilter(){
return new CorsFilter(configurationSource());
}
第二种解决方案
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 配置放行
.antMatchers("/subsystem/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
// 指定cors配置
.cors().configurationSource(configurationSource())
.and()
.formLogin().loginProcessingUrl("/admin/login").permitAll()
.successHandler(new AdminAuthenticationSuccessHandler())
.failureHandler(new AdminAuthenticationFailureHandler())
.and()
// 开启session,并限制并发登录数为1(不允许同一用户多端登录)
.sessionManagement()
.maximumSessions(1)
.expiredSessionStrategy(new AdminSessionInformationExpiredStrategy());
}
// cors配置
CorsConfigurationSource configurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("http://localhost:8080");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
url.registerCorsConfiguration("/**",corsConfiguration);
return url;
}
总结:
该问题主要的是因为security中两个放行方式的不同导致的。建议在HttpSecurity中配置放行。