Oauth2AuthenticationProcassingFilter解析
程序员文章站
2022-05-08 14:20:30
...
Spring Security Outh2的过滤器链如下图所示:
其中 SecurityContextPersistenceFilter用的是 NullSecurityContextRepository。 也就是说SecurityContextPersistenceFilter没有持久化SecurityContext, 这一步始终都是获取一个空的SecurityContext存放在SpringSecurityContextHolder中。
那么真正解析请求头部或者查询参数 Authorization 令牌的是什么呢? 是由 Oauth2AuthenticationProcassingFilter 进行解析的。
Oauth2AuthenticationProcassingFilter解析
TokenExtractor Token抽取器(比如:BearerTokenExtractor ), 用于解析参数获取Token信息, 返回PreAuthenticatedAuthenticationToken;
此时返回的 PreAuthenticatedAuthenticationToken 对象如下图所示
调用AuthenticationDetailsSource构建 details, 代码如下
public class OAuth2AuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, OAuth2AuthenticationDetails> { public OAuth2AuthenticationDetails buildDetails(HttpServletRequest context) { return new OAuth2AuthenticationDetails(context); } }
这一步执行完后 authentication状态如下:
认证授权,
调用 OAuth2AuthenticationManager对之前的authentication进行认证。
Authentication authResult = authenticationManager.authenticate(authentication);
对认证的逻辑展开下说明:
调用ResourceServerTokenServices (例如, DefaultTokenServices )中的loadAuthentication方法认证。其中有个重要的TokenStore, 我这里用的是JdbcTokenStore, 用于存取Token信息。还有ClientDetailsService接口, 用于判断clientId是否满足。
除了DefaultTokenServices外, 默认实现还有如下:
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException { OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); if (accessToken == null) { throw new InvalidTokenException("Invalid access token: " + accessTokenValue); } else if (accessToken.isExpired()) { tokenStore.removeAccessToken(accessToken); throw new InvalidTokenException("Access token expired: " + accessTokenValue); } OAuth2Authentication result = tokenStore.readAuthentication(accessToken); if (result == null) { // in case of race condition throw new InvalidTokenException("Invalid access token: " + accessTokenValue); } if (clientDetailsService != null) { String clientId = result.getOAuth2Request().getClientId(); try { clientDetailsService.loadClientByClientId(clientId); } catch (ClientRegistrationException e) { throw new InvalidTokenException("Client not valid: " + clientId, e); } } return result; }
认证成功后,调用Spring Security核心类 SecurityContextHolder 初始化Context上下文信息。
SecurityContextHolder.getContext().setAuthentication(authResult);