(1). 概述
在这一小篇,开始对Spring Security与Oauth2进行整合的源码进行剖析,需要找到Oauth2对Spring Security进行了哪些扩展.
(2). 切入点(@EnableAuthorizationServer)
// Endpoint典型的请求入站消息配置
@Import({AuthorizationServerEndpointsConfiguration.class, AuthorizationServerSecurityConfiguration.class})
public @interface EnableAuthorizationServer {
}
(3). AuthorizationServerEndpointsConfiguration
@Configuration
@Import(TokenKeyEndpointRegistrar.class)
public class AuthorizationServerEndpointsConfiguration {
// ******************************************************************************************************
// 1. 创建一个:AuthorizationServerEndpointsConfigurer
// ******************************************************************************************************
private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();
// ******************************************************************************************************
// 2. 注入开发配置的:ClientDetailsService
// ******************************************************************************************************
@Autowired
private ClientDetailsService clientDetailsService;
// ******************************************************************************************************
// 3. 注入开发配置的:AuthorizationServerConfigurer集合
// ******************************************************************************************************
@Autowired
private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();
// ******************************************************************************************************
// 4. 遍历开发配置的:AuthorizationServerConfigurer,设置到Global:AuthorizationServerEndpointsConfigurer
// ******************************************************************************************************
@PostConstruct
public void init() {
for (AuthorizationServerConfigurer configurer : configurers) {
try {
configurer.configure(endpoints);
} catch (Exception e) {
throw new IllegalStateException("Cannot configure enpdoints", e);
}
}
// 设置:ClientDetailsService
endpoints.setClientDetailsService(clientDetailsService);
}
// ******************************************************************************************************
// /oauth/confirm_access 请求处理
// 5. 我一直以为Oauth2会像Spring Security一样,写一堆的Filter,结果:你会发现,超出你的想象.
// Oauth2压根就没有写Filter,而是直接利用注解(二次封装):@org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint,向SpringMVC中注册Mapping.
// ******************************************************************************************************
@Bean
public AuthorizationEndpoint authorizationEndpoint() throws Exception {
AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
authorizationEndpoint.setTokenGranter(tokenGranter());
authorizationEndpoint.setClientDetailsService(clientDetailsService);
authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
return authorizationEndpoint;
}
// ******************************************************************************************************
// 6. /oauth/token 请求处理(拿着code换access_token,以及拿着refresh_token换access_token)
// 向SpringMVC中注册了一个Mapping
// ******************************************************************************************************
@Bean
public TokenEndpoint tokenEndpoint() throws Exception {
TokenEndpoint tokenEndpoint = new TokenEndpoint();
tokenEndpoint.setClientDetailsService(clientDetailsService);
tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
tokenEndpoint.setTokenGranter(tokenGranter());
tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
return tokenEndpoint;
}
// ******************************************************************************************************
// 7. /oauth/check_token 请求处理
// 向SpringMVC中注册了一个Mapping
// ******************************************************************************************************
@Bean
public CheckTokenEndpoint checkTokenEndpoint() {
CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices());
endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter());
endpoint.setExceptionTranslator(exceptionTranslator());
return endpoint;
}
// ******************************************************************************************************
// 8. 认证成功后的URL处理:/oauth/confirm_access
// ******************************************************************************************************
@Bean
public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() {
return new WhitelabelApprovalEndpoint();
}
// ******************************************************************************************************
// 9. 认证失败后的URL处理:/oauth/error
// ******************************************************************************************************
@Bean
public WhitelabelErrorEndpoint whitelabelErrorEndpoint() {
return new WhitelabelErrorEndpoint();
}
}
(4). 总结
在没有看源码之前,自己猜测是:Oauth2会自定义一堆的Filter,结果,超出你的预料,不过,这样有一个好处就是能扩展你的知识(毕竟:条条大路通罗马),有一点不解的是:Filter相比SpringMVC Mapping来说,Filter会更加的通用一些(比如:Struts与Oauth2结合怎么办).不知道Oauth2的作者是怎么想的?