spring.sercurity.oauth2资源服务器检查token过程

在使用spring.sercurity.oauth2配置资源服务器时,发现只配置了个ResourceServerConfigurerAdapter的实现类,就可以自己检查token的有效性了,不太理解,百度和debug看了一下源码明白了,大概流程如下

首先我在application.xml中配置了我的认证中心的相关参数

#指定使用的认证中心,如果不配置会使用默认认证中心
security:
  oauth2:
    client:
      client-id: client
      client-secret: secret
      access-token-uri: http://localhost:9997/oauth/token
      user-authorization-uri: http://localhost:9997/oauth/authorize
    resource:
      token-info-uri: http://localhost:9997/oauth/check_token

当有请求过来请求资源服务器接口时,会被引用的spring.sercurity.oauth2框架接管,被OAuth2AuthenticationProcessingFilter 拦截器拦截,

拦截器源码

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        boolean debug = logger.isDebugEnabled();
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;

        try {
            Authentication authentication = this.tokenExtractor.extract(request);
            if (authentication == null) {
                if (this.stateless && this.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(this.authenticationDetailsSource.buildDetails(request));
                }
				/*********重点在这里***********/	
                Authentication authResult = this.authenticationManager.authenticate(authentication);
                /****************************/
                if (debug) {
                    logger.debug("Authentication success: " + authResult);
                }

                this.eventPublisher.publishAuthenticationSuccess(authResult);
                SecurityContextHolder.getContext().setAuthentication(authResult);
            }
        } catch (OAuth2Exception var9) {
            SecurityContextHolder.clearContext();
            if (debug) {
                logger.debug("Authentication request failed: " + var9);
            }

            this.eventPublisher.publishAuthenticationFailure(new BadCredentialsException(var9.getMessage(), var9), new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
            this.authenticationEntryPoint.commence(request, response, new InsufficientAuthenticationException(var9.getMessage(), var9));
            return;
        }

        chain.doFilter(request, response);
    }

进入authenticationManager.authenticate(authentication)发现authenticationManager是个接口,具体实现在OAuth2AuthenticationManager中,

 public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if (authentication == null) {
            throw new InvalidTokenException("Invalid token (token not found)");
        } else {
            String token = (String)authentication.getPrincipal();
            /********重点在这里*********/
            OAuth2Authentication auth = this.tokenServices.loadAuthentication(token);
            /*************************/
            if (auth == null) {
                throw new InvalidTokenException("Invalid token: " + token);
            } else {
                Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
                if (this.resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(this.resourceId)) {
                    throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + this.resourceId + ")");
                } else {
                    this.checkClientDetails(auth);
                    if (authentication.getDetails() instanceof OAuth2AuthenticationDetails) {
                        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
                        if (!details.equals(auth.getDetails())) {
                            details.setDecodedDetails(auth.getDetails());
                        }
                    }

                    auth.setDetails(authentication.getDetails());
                    auth.setAuthenticated(true);
                    return auth;
                }
            }
        }
    }

tokenServices也是接口,具体实现在RemoteTokenServices

public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {
        MultiValueMap<String, String> formData = new LinkedMultiValueMap();
        formData.add(this.tokenName, accessToken);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", this.getAuthorizationHeader(this.clientId, this.clientSecret));
        /***********使用restTemplate发送校验token请求*************/
        Map<String, Object> map = this.postForMap(this.checkTokenEndpointUrl, formData, headers);
        /*****************************************************/
        if (map.containsKey("error")) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("check_token returned error: " + map.get("error"));
            }

            throw new InvalidTokenException(accessToken);
        } else if (!Boolean.TRUE.equals(map.get("active"))) {
            this.logger.debug("check_token returned active attribute: " + map.get("active"));
            throw new InvalidTokenException(accessToken);
        } else {
            return this.tokenConverter.extractAuthentication(map);
        }
    }

到此基本明白资源服务器校验token流程了,其中请求路径的checkTokenEndpointUrl是在资源服务器启动的时候,通过加载appliaction.yml文件读取我配置的认证url加载的

你可能感兴趣的:(spring.sercurity.oauth2资源服务器检查token过程)