从 Angular 调用到 Spring 启用安全 OAuth 的服务器时出现 CORS 错误
CORS error when calling from Angular to Spring Security OAuth enabled server
我有一个 Angular 项目,它将发送一个 header 授权,值为 Bearer 。
UI 被集成到 Keycloak 并且令牌被刷新并放置在 header 到 angular 拦截器上,在 UI.
上一切正常
在 REST 上,服务器运行 Spring Boot + Spring Security + OAuth2ResourceServer。
我有一个安全配置 class,它启用了 Spring 安全性,它创建了默认的 cors 过滤器。
但我在浏览器 运行 上 http://localhost:4200 上收到 CORS 错误。
所以我在 SpringApplication class.
中创建了一个单独的 CorsFilter bean
@Bean
public CorsFilter getCorsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOriginPatterns(Arrays.asList("http://localhost:4200"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
我仍然在 UI 上收到 CORS 错误。
Spring 下面的安全配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.antMatchers(HttpMethod.POST)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
分析了一天想通了自定义默认的CorsFilter。
spring 安全性无法识别我定义的新 CorsFilter bean。所以我必须如下自定义 http.cors()
。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {// @formatter:off
http.cors(corsCustomiser())
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.antMatchers(HttpMethod.POST)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}//@formatter:on
private Customizer<CorsConfigurer<HttpSecurity>> corsCustomiser() {
return new Customizer<CorsConfigurer<HttpSecurity>>() {
@Override
public void customize(CorsConfigurer<HttpSecurity> t) {
t.configurationSource(getCorsConfiguration());
}
};
}
private CorsConfigurationSource getCorsConfiguration() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOriginPatterns(Arrays.asList("http://localhost:4200"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return source;
}
}
首先添加“/oauth/token”如下:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/oauth/token");
}
然后设置过滤器:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
public class CorsFilter implements Filter {
public CorsFilter() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
response.setHeader("Access-Control-Max-Age", "3600");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
我有一个 Angular 项目,它将发送一个 header 授权,值为 Bearer
在 REST 上,服务器运行 Spring Boot + Spring Security + OAuth2ResourceServer。
我有一个安全配置 class,它启用了 Spring 安全性,它创建了默认的 cors 过滤器。
但我在浏览器 运行 上 http://localhost:4200 上收到 CORS 错误。
所以我在 SpringApplication class.
中创建了一个单独的 CorsFilter bean@Bean
public CorsFilter getCorsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOriginPatterns(Arrays.asList("http://localhost:4200"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
我仍然在 UI 上收到 CORS 错误。
Spring 下面的安全配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.antMatchers(HttpMethod.POST)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
分析了一天想通了自定义默认的CorsFilter。
spring 安全性无法识别我定义的新 CorsFilter bean。所以我必须如下自定义 http.cors()
。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {// @formatter:off
http.cors(corsCustomiser())
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.antMatchers(HttpMethod.POST)
.hasAnyAuthority("SCOPE_read", "SCOPE_profile", "ROLE_USER")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}//@formatter:on
private Customizer<CorsConfigurer<HttpSecurity>> corsCustomiser() {
return new Customizer<CorsConfigurer<HttpSecurity>>() {
@Override
public void customize(CorsConfigurer<HttpSecurity> t) {
t.configurationSource(getCorsConfiguration());
}
};
}
private CorsConfigurationSource getCorsConfiguration() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOriginPatterns(Arrays.asList("http://localhost:4200"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return source;
}
}
首先添加“/oauth/token”如下:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/oauth/token");
}
然后设置过滤器:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
public class CorsFilter implements Filter {
public CorsFilter() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
response.setHeader("Access-Control-Max-Age", "3600");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}