资源服务器
继承关系图
OAuth2AuthenticationProcessingFilter
资源资源服务器的主角:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
final boolean debug = logger.isDebugEnabled();
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
try {
// 提取token
Authentication authentication = tokenExtractor.extract(request);
// 如果token为null 判断是已认证 如果是的 则 清空上下文 并输出相关日志
if (authentication == null) {
if (stateless && isAuthenticated()) {
if (debug) {
logger.debug("Clearing security context.");
}
SecurityContextHolder.clearContext();
}
if (debug) {
logger.debug("No token in request, will continue chain.");
}
} else {
request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
if (authentication instanceof AbstractAuthenticationToken) {
AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
}
// 这个是核心方法 也就是拿着当前的token 进行认证 认证方法是下文中的方法
Authentication authResult = authenticationManager.authenticate(authentication);
if (debug) {
logger.debug("Authentication success: " + authResult);
}
// 事件触发器 进行广播 授权成功
eventPublisher.publishAuthenticationSuccess(authResult);
// 将认证信息存储到上下文中
SecurityContextHolder.getContext().setAuthentication(authResult);
}
}
catch (OAuth2Exception failed) {
SecurityContextHolder.clearContext();
if (debug) {
logger.debug("Authentication request failed: " + failed);
}
eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed),
new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
authenticationEntryPoint.commence(request, response,
new InsufficientAuthenticationException(failed.getMessage(), failed));
return;
}
// 调用下个过滤连
chain.doFilter(request, response);
}
OAuth2AuthenticationManager
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Authentication authentication 其实就是token的一个存储对象
// 如果 authentication 为null 也就是 请求中不携带token 则直接提示常见的 无效token异常信息
if (authentication == null) {
throw new InvalidTokenException("Invalid token (token not found)");
}
// 取出token 使用 ResourceServerTokenServices.loadAuthentication()去加载token (这里应该就是解析token的地方)
// ResourceServerTokenServices 是一个接口 他有四种实现
// DefaultTokenServices
// RemoteTokenServices
// SpringSocialTokenServices
// UserInfoTokenServices
//这里调用的是默认实现(DefaultTokenServices) 其余三种未研究作用 已经调用场景
String token = (String) authentication.getPrincipal();
OAuth2Authentication auth = tokenServices.loadAuthentication(token);
// 如果token解析到的 OAuth2Authentication 对象为空 , 则提示失效的token
if (auth == null) {
throw new InvalidTokenException("Invalid token: " + token);
}
// resourceIds就是自己 在AuthorizationServerConfig.configure(ClientDetailsServiceConfigurer clients)中配置的客户端详情
// 这里就是校验 客户端Id是否存在 不存在则提示 失效的token 资源ids 中不包含该token的资源id
// token中的 资源Id 是来源于 申请token是传入的客户端id
Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {