Oauth2之ClientCredentialsTokenEndpointFilter学习

Oauth2之ClientCredentialsTokenEndpointFilter学习

在配置授权服务器的时候,都会在这样写:

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.realm("simple")
            //使用标准的spel语言就行
            //默认都是denyAll()
            //exposes public key for token verification if using JWT tokens
            .tokenKeyAccess("permitAll()")
            //used by Resource Servers to decode access tokens
            .checkTokenAccess("isAuthenticated()")
            //allowFormAuthenticationForClients是为了注册clientCredentialsTokenEndpointFilter
            //clientCredentialsTokenEndpointFilter,解析request中的client_id和client_secret
            //构造成UsernamePasswordAuthenticationToken,然后通过UserDetailsService查询作简单的认证而已
            //一般是针对password模式和client_credentials
            //当然也可以使用http basic认证
            //如果使用了http basic认证,就不用使用clientCredentialsTokenEndpointFilter
            //因为本质是一样的
            .allowFormAuthenticationForClients();
}

filter and authentication endpoint for the OAuth2 Token Endpoint. Allows clients to authenticate using request parameters if included as a security filter, as permitted by the specification (but not recommended). It is recommended by the specification that you permit HTTP basic authentication for clients, and not use this filter at all(大概的意思是:ClientCredentialsTokenEndpointFilter是Oauth2 Token Endpoint的认证端口,如果使用了这条安全过滤器,就会通过请求参数去对客户端进行认证。规范中是允许的[但不推荐],而更倾向推荐使用HTTP basic认证,一旦使用HTTP basic认证之后,就不需要使用这个过滤器了)

核心部分

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
    throws AuthenticationException, IOException, ServletException {

      if (allowOnlyPost && !"POST".equalsIgnoreCase(request.getMethod())) {
        throw new HttpRequestMethodNotSupportedException(request.getMethod(), new String[] { "POST" });
      }

      String clientId = request.getParameter("client_id");
      String clientSecret = request.getParameter("client_secret");

      // If the request is already authenticated we can assume that this
      // filter is not needed
      Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
      //感觉这个判断是为了对Authorization_code模式和Implicit隐式模式进行过滤 ?????
      if (authentication != null && authentication.isAuthenticated()) {
        return authentication;
      }

      if (clientId == null) {
        throw new BadCredentialsException("No client credentials presented");
      }

      if (clientSecret == null) {
        clientSecret = "";
      }

      clientId = clientId.trim();
      //将clientId和clientSecret构造成UsernamePasswordAuthenticationToken
      UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId,
          clientSecret);

      return this.getAuthenticationManager().authenticate(authRequest);

}

认证流程:
1. 从request中解析client_idclient_secret
2. 将clientIdclientSecret构造成UsernamePasswordAuthenticationToken,交给ProviderManager,然后ProviderManager代理AuthenticationProvider去认证,最后真正执行的是DaoAuthenticationProvider,通过UserDetailsService.loadUserByUsername向表oauth_client_details查询clientDetails信息

你可能感兴趣的:(oauth2)