所以我有以下从 this example 浓缩的授权服务器来自戴夫·赛尔
@SpringBootApplication
public class AuthserverApplication {
public static void main(String[] args) {
SpringApplication.run(AuthserverApplication.class, args);
}
/* added later
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
protected static class MyWebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http //.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
}
}*/
@Configuration
@EnableAuthorizationServer
protected static class OAuth2AuthorizationConfig extends
AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
new ClassPathResource("keystore.jks"), "foobar".toCharArray())
.getKeyPair("test");
converter.setKeyPair(keyPair);
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
//.secret("acmesecret")
.authorizedGrantTypes(//"authorization_code", "refresh_token",
"password").scopes("openid");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager).accessTokenConverter(
jwtAccessTokenConverter());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
"isAuthenticated()");
}
}
}
当我运行它并用 curl 测试它时
curl acme@localhost:8110/oauth/token -d grant_type=password -d client_id=acme -d username=user -d password=password
我得到一个 JWT 作为响应,但是当我尝试从我的前端(不同端口上的 Angular JS)访问 AuthServer 时,我得到了 CORS 错误。不是因为缺少 header ,而是因为 OPTION 请求被拒绝并且缺少凭据。
Request URL:http://localhost:8110/oauth/token
Request Method:OPTIONS
Status Code:401 Unauthorized
WWW-Authenticate:Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"
我已经知道我必须添加一个 CorsFilter 并且另外发现了 this post我使用第一个答案的片段来让 OPTIONS 请求访问
/oauth/token
没有凭据:
@Order(-1)
public class MyWebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
}
}
之后,我得到了 curl 以下错误:
{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"}
所以为了简单起见,我只是添加了
http.csrf().disable()
到
configure
MyWebSecurity 类的方法,它解决了 OPTION 请求的问题,但因此 POST 请求不再工作,我得到
There is no client authentication. Try adding an appropriate authentication filter.
(也有 curl )。
我试图找出是否必须以某种方式连接 MyWebSecurity 类和 AuthServer,但没有任何运气。原始示例(开头的链接)也注入(inject)了 authenticationManager,但这对我来说没有任何改变。
请您参考如下方法:
找到了我的问题的原因!
如果 CorsFilter 处理了 OPTIONS 请求,我只需要结束过滤器链并立即返回结果!
SimpleCorsFilter.java
@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() {
}
}
之后,我可以忽略 AuthServer =D 中的 OPTIONS 预检请求
所以服务器就像上面的截图一样工作,你可以在开始时忽略 MyWebSecurity 类的 block 注释。