1.问题由来
以前只用spring-security做权限认证,也遇到过跨域问题主要是在后端的继承WebSecurityConfigurerAdapter 的类中配置下面的bean,然后前端vue配置代理来解决。
/**
*Security推荐的跨域配置
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); //同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔;
corsConfiguration.addAllowedHeader("*");//header,允许哪些header,本案中使用的是token,此处可将*替换为token;
corsConfiguration.addAllowedMethod("*"); //允许的请求方法,PSOT、GET等
corsConfiguration.setAllowCredentials(true);//允许携带cookie
((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允许跨域访问的url
return source;
}
但是换成spring-security-oauth2后由于自己重写了LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter 的登陆验证导致跨域问题重现。而且这次我没有使用cookie也导致了很多变化,大多数验证数据都是用redis来实现的。
2.报错信息
Access to XMLHttpRequest at 'http://localhost:81/' from origin 'http://localhost' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Access to XMLHttpRequest at 'http://localhost:81/' from origin 'http://localhost' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource
3.解决配置
创建配置类
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
//config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
在资源认证服务器或者WebSecurityConfigurerAdapter 的继承类中配置
(因为使用的是spring-security-oauth2所以推荐在资源认证服务器中ResourceServerConfigurerAdapter)
.antMatchers(HttpMethod.OPTIONS).permitAll()//跨域请求会先进行一次options请求
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.requestMatchers().anyRequest()
.and()
.anonymous()
.and()
.authorizeRequests()
.antMatchers(
"/webjars/**",
"/swagger/**",
"/v2/api-docs",
"/doc.html",
"/swagger-ui.html",
"/swagger-resources/**",
"/open/**","/oauth/**").permitAll()
.antMatchers(HttpMethod.OPTIONS).permitAll()//跨域请求会先进行一次options请求
.and()
.authorizeRequests()
.antMatchers("/**").authenticated();//配置所有访问控制,必须认证过后才可以访问
// @formatter:on
}
效果
4.特别注意
(一) 当前端配置withCredentials=true时, 后端配置Access-Control-Allow-Origin不能为*, 必须是相应地址
(二) 当配置withCredentials=true时, 后端需配置Access-Control-Allow-Credentials
(三) 当前端配置请求头时, 后端需要配置Access-Control-Allow-Headers为对应的请求头集合
以前应为需要携带cookie所以配置了,但是因为现在不使用且会导致和后端配置冲突所以将其注释