oauth2源码解析/oauth/token干了些什么?

最近作了两个项目,基于各类缘由,安全框架都是使用的Oauth2,以前对oauth2的了解也只是停留在使用的层面,知道有资源服务器,认证服务器,四种认证方式,可是对于其中的源码以及缘由,没有深刻的分析过,最近结合大师(程序员DD)的博客(http://blog.didispace.com/spr...),以及本身断点查看源码,对oauth的源码有了本身的分析,若有不周,还望各位大虾提出。我主要从如下几点分析:程序员

1.入口接口:/oath/token;/oauth/check_token;

一.程序的入口:/oath/tokenredis

使用过oauth的童鞋都知道,当咱们的oauth配置好以后,百分百会调用这个url去拿到咱们的token,不论你是使用的get,仍是post方式,均可以。他的入口在这个类:TokenEndpointspring

@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {
    //
    ...

    //若是是get请求,走这里
    @RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
    public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
    Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
        if (!allowedRequestMethods.contains(HttpMethod.GET)) {
            throw new HttpRequestMethodNotSupportedException("GET");
        }
        
        //get请求最终仍是调用了post请求
        return postAccessToken(principal, parameters);
    }
    
    //post方式获取token
    @RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
    public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
    Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {

        if (!(principal instanceof Authentication)) {
            throw new InsufficientAuthenticationException(
                    "There is no client authentication. Try adding an appropriate authentication filter.");
        }
        
        //拿到客户端id
        String clientId = getClientId(principal);
        ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);

        //这一步把获取token的基础信息封装成了一个类
        TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);

        //如下的判断都在作校验
        if (clientId != null && !clientId.equals("")) {
            // Only validate the client details if a client authenticated during this
            // request.
            if (!clientId.equals(tokenRequest.getClientId())) {
                // double check to make sure that the client ID in the token request is the same as that in the
                // authenticated client
                throw new InvalidClientException("Given client ID does not match authenticated client");
            }
        }
        if (authenticatedClient != null) {
            oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
        }
        if (!StringUtils.hasText(tokenRequest.getGrantType())) {
            throw new InvalidRequestException("Missing grant type");
        }
        if (tokenRequest.getGrantType().equals("implicit")) {
            throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
        }

        if (isAuthCodeRequest(parameters)) {
            // The scope was requested or determined during the authorization step
            if (!tokenRequest.getScope().isEmpty()) {
                logger.debug("Clearing scope of incoming token request");
                tokenRequest.setScope(Collections.<String> emptySet());
            }
        }

        if (isRefreshTokenRequest(parameters)) {
            // A refresh token has its own default scopes, so we should ignore any added by the factory here.
            tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
        }

        //重点:这一步调用了获取token的方法
        OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
        if (token == null) {
            throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
        }

        return getResponse(token);

    }
    //其余代码省略
    ...
}

咱们顺着获取token的方法往下走,发现其调用了DefaultTokenServices的createAccessToken方法,里面则使用了tokenStore.getAccessToken(authentication)来获取的token,这个tokenStore具体是哪一个实现类的对象,还要看咱们在认证服务器(即继承了AuthorizationServerConfigurerAdapter类),里面的bean:tokenStore,个人以下:安全

@Bean
public TokenStore tokenStore() {
    return new CrawlerRedisTokenStore(redisConnectionFactory);
}

//固然,也可使用默认的几个实现类,好比InMemoryTokenStore,JdbcTokenStore,
//JwtTokenStore,RedisTokenStore,我这里由于有其余需求,全部新建了一个实现类。

找到 tokenStore.getAccessToken(authentication)后,发现里面这句话,生成了token,个人token是存在redis的,他会先在reids里面找若是有token就拿出来,没有或者失效了,就从新生成一个.服务器

OAuth2AccessToken accessToken = deserializeAccessToken(bytes);
相关文章
相关标签/搜索