主要过滤器
ClientCredentialsTokenEndpointFilter
作用
首先进行过滤
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
if (!this.requiresAuthentication(request, response)) {
chain.doFilter(request, response);
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Request is to process authentication");
}
Authentication authResult;
try {
authResult = this.attemptAuthentication(request, response);
if (authResult == null) {
return;
}
this.sessionStrategy.onAuthentication(authResult, request, response);
} catch (InternalAuthenticationServiceException var8) {
this.logger.error("An internal error occurred while trying to authenticate the user.", var8);
this.unsuccessfulAuthentication(request, response, var8);
return;
} catch (AuthenticationException var9) {
this.unsuccessfulAuthentication(request, response, var9);
return;
}
if (this.continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
this.successfulAuthentication(request, response, chain, authResult);
}
}
从请求中获取 client_id,client_id_secret,
组成UsernamePasswordAuthenticationToken
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String clientId = request.getParameter("client_id");
String clientSecret = request.getParameter("client_secret");
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId, clientSecret);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
AuthenticationManager 具体的鉴权管理器
实现类一般是ProviderManager。而ProviderManager内部维护了一个List,
真正的身份认证是由一系列AuthenticationProvider去完成。而AuthenticationProvider
的常用实现类则是DaoAuthenticationProvider,DaoAuthenticationProvider
内部又聚合了一个UserDetailsService接口,UserDetailsService才是获取用户详细信息的最终接口。
之后验证请求到了 TokenEndpoint
@RequestMapping( value = {"/oauth/token"}, method = {RequestMethod.POST} )
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
...
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
...
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
...
return getResponse(token);
}
使用 TokenGranter 来计算token
TokenGranter的设计思路是使用CompositeTokenGranter管理一个List列表,
每一种grantType对应一个具体的真正授权者,通过grantType来区分是否是各自的授权类型。
如
ResourceOwnerPasswordTokenGranter 账号密码
AuthorizationCodeTokenGranter 授权码模式
ClientCredentialsTokenGranter 客户端模式
ImplicitTokenGranter 简化模式
RefreshTokenGranter 刷新token专用
每一种token时实现了 TokenGranter接口
public interface TokenGranter {
OAuth2AccessToken grant(String var1, TokenRequest var2);
}
实际验证的TokenGranter继承自抽象类 AbstractTokenGranter
public abstract class AbstractTokenGranter implements TokenGranter {
protected final Log logger = LogFactory.getLog(this.getClass());
private final AuthorizationServerTokenServices tokenServices;
private final ClientDetailsService clientDetailsService;
private final OAuth2RequestFactory requestFactory;
private final String grantType;
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
}
protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) {
return this.tokenServices.createAccessToken(this.getOAuth2Authentication(client, tokenRequest));
}
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
}
protected void validateGrantType(String grantType, ClientDetails clientDetails) {
}
protected AuthorizationServerTokenServices getTokenServices() {
}
protected OAuth2RequestFactory getRequestFactory() {
}
}
Token具体的刷新创建由AuthorizationServerTokenServices 来实现
public interface AuthorizationServerTokenServices {
OAuth2AccessToken createAccessToken(OAuth2Authentication var1) throws AuthenticationException;
OAuth2AccessToken refreshAccessToken(String var1, TokenRequest var2) throws AuthenticationException;
OAuth2AccessToken getAccessToken(OAuth2Authentication var1);
}
默认的TokenService
public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {
private int refreshTokenValiditySeconds = 2592000;
private int accessTokenValiditySeconds = 43200;
private boolean supportRefreshToken = false;
private boolean reuseRefreshToken = true;
private TokenStore tokenStore;
private ClientDetailsService clientDetailsService;
private TokenEnhancer accessTokenEnhancer;
private AuthenticationManager authenticationManager;
public DefaultTokenServices() {
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.tokenStore, "tokenStore must be set");
}
@Transactional
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
}
@Transactional(
noRollbackFor = {InvalidTokenException.class, InvalidGrantException.class}
)
public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException {
}
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
return this.tokenStore.getAccessToken(authentication);
}
private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) {
}
public OAuth2AccessToken readAccessToken(String accessToken) {
return this.tokenStore.readAccessToken(accessToken);
}
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException {
}
public String getClientId(String tokenValue) {
}
public boolean revokeToken(String tokenValue) {
}
private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
}
private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
}
...
}