以下是我使用 Angular 1.5 应用程序发出请求时在 Chrome 控制台中得到的信息:
XMLHttpRequest cannot load http://localhost:8080/api/oauth/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 401.
当我删除 OAuth2 配置时,错误消失了。
这是我的 CORS 配置:
class AppWebSpringConfig extends WebMvcConfigurerAdapter implements ServletContextAware {
...
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("X-Requested-With", "X-Auth-Token", "Origin", "Content-Type", "Accept")
.allowCredentials(false)
.maxAge(3600);
}
...
}
还有我的 OAuth2 配置类:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
@Configuration
class OAuth2ServerConfiguration {
private static final int ONE_HOUR = 3600;
private static final int THIRTY_DAYS = 2592000;
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.anyRequest().authenticated();
// @formatter:on
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private UserSecurityService userSecurityService;
@Autowired
private DataSource dataSource;
@Autowired
private Environment env;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// @formatter:off
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userSecurityService);
// @formatter:on
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients
.jdbc(dataSource)
.withClient(env.getProperty(CLIENT_ID_WEB))
.secret(env.getProperty(CLIENT_SECRET_WEB))
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(ONE_HOUR)
.refreshTokenValiditySeconds(THIRTY_DAYS);
// @formatter:on
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore());
return tokenServices;
}
}
}
编辑:我还尝试了以下过滤器实现,但它不起作用。我在 doFilter() 方法中放置了一个断点,但执行并没有在那里停止,就像我的过滤器没有注册一样。但是,当我向过滤器添加默认构造函数并在那里放置断点时,它停止了,这意味着过滤器已注册。
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
public SimpleCorsFilter() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
我也尝试过这种方法,但再次没有运气:Allow OPTIONS HTTP Method for oauth/token request
我认为 OAuth2 配置不允许请求甚至通过配置的 CORS 过滤器。 有人知道这个问题的解决方案吗?
编辑2: 所以,原来有一个类:
public class AppSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
// nothing here, using defaults
}
一旦我评论它,CORS 配置就开始工作(可能是由于过滤器通过),但现在我的 OAuth2 配置根本不起作用!每个 URL 都是公开的,没有安全性。有什么想法吗?
最佳答案
嗨,我在 spring 4.3 上遇到了同样的问题,但在这里解决了答案:-
您需要在 AuthorizationServerConfiguration 类中重写 AuthorizationServerConfigurerAdapter 的以下方法,并使用 AuthorizationServerSecurityConfigurer 的 addTokenEndpointAuthenticationFilter 方法在其中添加 CORS 过滤器,如下所示:-
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.addTokenEndpointAuthenticationFilter(new CORSFilter());
}
您的 AuthorizationServerConfiguration 类将是:-
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private UserSecurityService userSecurityService;
@Autowired
private DataSource dataSource;
@Autowired
private Environment env;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// @formatter:off
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userSecurityService);
// @formatter:on
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients
.jdbc(dataSource)
.withClient(env.getProperty(CLIENT_ID_WEB))
.secret(env.getProperty(CLIENT_SECRET_WEB))
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(ONE_HOUR)
.refreshTokenValiditySeconds(THIRTY_DAYS);
// @formatter:on
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore());
return tokenServices;
}
// ***** Here I added CORS filter *****
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.addTokenEndpointAuthenticationFilter(new CORSFilter());
}
}
关于spring - CORS 不适用于带有 OAuth2 的 Spring 4.3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39191309/