错误情况
项目中包含 Spring Security 就会有 401 的问题,Spring Security 本身是通过 Filter 实现的,如果没有对其单独做 CORS 的处理,在 Web Security 报错 401 的时候是不会返回相应的 CORS 的字段的。这会导致出现的 401 错误成为了一个无法进行跨域的错误,导致前端程序无法正常的处理 401 相应 。对于spring security oauth2 默认接口,例如 /oauth/token 跨域问题,可以通过全局 CORS Filter 解决
解决办法
1、在spring boot项目中配置跨域
@Configuration
public class MyCorsConfiguration {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1
corsConfiguration.addAllowedHeader("*"); // 2
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedMethod("*"); // 3
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}
2、设置对/oauth/路径的特殊处理
在函数头中加入注解:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-1)
在config中加入
http.requestMatchers().antMatchers(HttpMethod.OPTIONS, "/oauth/**")
.and()
.cors()
.and()
.csrf().disable();
代码展示
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-1)
public class WebsecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().accessDeniedHandler(new InterestAccessDeniedHandler());
http.authorizeRequests().anyRequest().authenticated();
http.requestMatchers().antMatchers(HttpMethod.OPTIONS, "/oauth/**")
.and()
.cors()
.and()
.csrf().disable();
// http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/oauth/**");
http.formLogin().failureUrl("/login?error").permitAll();
http.logout().permitAll();
http.csrf().disable();
}
// 配置内存模式的用户
/*
* @Bean
*
* @Override protected UserDetailsService userDetailsService(){
* InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
* manager.createUser(User.withUsername("test").password("123").authorities(
* "USER").build());
* manager.createUser(User.withUsername("test1").password("123").authorities(
* "USER").build()); return manager; }
*/
/**
* 需要配置这个支持password模式 support password grant type
*
* @return
* @throws Exception
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}