一 代码位置
https://github.com/cakin24/oauth2-demo/tree/master/client-credentials
二 参考文章
http://www.spring4all.com/article/451
三 获取token方式
http://localhost:8080/oauth/token?client_id=client_1&client_secret=123456&scope=select&grant_type=client_credentials
四 关键类
- ClientCredentialsTokenEndpointFilter:客户端身份认证核心过滤器
- AuthenticationManager:顶级身份管理者
- ProviderManager:顶级身份管理器AuthenticationManager去进行身份认证(AuthenticationManager的实现类一般是ProviderManager)。
- AuthenticationProvider:ProviderManager内部维护了一个List<AuthenticationProvider>,真正的身份认证是由一系列AuthenticationProvider去完成。
- DaoAuthenticationProvider:AuthenticationProvider的常用实现类是DaoAuthenticationProvider,DaoAuthenticationProvider内部又聚合了一个UserDetailsService接口,UserDetailsService才是获取用户详细信息的最终接口。
- TokenEndpoint:1 加载客户端信息 2 结合请求信息,创建TokenRequest 3 将TokenRequest传递给TokenGranter颁发token
- TokenGranter:TokenGranter的设计思路是使用CompositeTokenGranter管理一个List<TokenGranter>列表,每一种grantType对应一个具体的真正授权者,在debug过程中可以发现CompositeTokenGranter 内部就是在循环调用五种TokenGranter实现类的grant方法,而granter内部则是通过grantType来区分是否是各自的授权类型。
- AuthorizationServerTokenServices:AuthorizationServer端的token操作service
- ResourceOwnerPasswordTokenGranter:password密码模式
- AuthorizationCodeTokenGranter:authorization_code授权码模式
- ClientCredentialsTokenGranter:client_credentials客户端模式
- ImplicitTokenGranter:implicit简化模式
- RefreshTokenGranter:refresh_token 刷新token专用
五 认证UML类图
用来从请求中获取client_id,client_secret,组装成一个UsernamePasswordAuthenticationToken作为身份标识,使用容器中的顶级身份管理器AuthenticationManager去进行身份认证(AuthenticationManager的实现类一般是ProviderManager。而ProviderManager内部维护了一个List<AuthenticationProvider>,真正的身份认证是由一系列AuthenticationProvider去完成。而AuthenticationProvider的常用实现类则是DaoAuthenticationProvider,DaoAuthenticationProvider内部又聚合了一个UserDetailsService接口,UserDetailsService才是获取用户详细信息的最终接口,当我们在内存中配置用户,就是使用了UserDetailsService的一个实现类InMemoryUserDetailsManager。
六 TokenGranter接口的设计类图
TokenGranter的设计思路是使用CompositeTokenGranter管理一个List<TokenGranter>列表,每一种grantType对应一个具体的真正授权者,在debug过程中可以发现CompositeTokenGranter 内部就是在循环调用五种TokenGranter实现类的grant方法,而granter内部则是通过grantType来区分是否是各自的授权类型。
七 关于认证的关键类以及断点设置
AbstractAuthenticationProcessingFilter
ClientCredentialsTokenEndpointFilter
ProviderManager
AbstractUserDetailsAuthenticationProvider
DaoAuthenticationProvider
ClientDetailsUserDetailsService
InMemoryClientDetailsService
以上这些断点调试反映了认证的关键过程,整个过程的的思想是:把 http://localhost:8080/oauth/token?client_id=client_1&client_secret=123456&scope=select&grant_type=client_credentials中的client_id和client_secret和配置中的用户和密码进行比对,通过则进行第八步。
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//配置两个客户端,一个用于password认证一个用于client认证
clients.inMemory().withClient("client_1") //比对项
.resourceIds(DEMO_RESOURCE_ID)
.authorizedGrantTypes("client_credentials")
.scopes("select")
.authorities("oauth2")
.secret("123456") //比对项
.and().withClient("client_2")
.resourceIds(DEMO_RESOURCE_ID)
.authorizedGrantTypes("password", "refresh_token")
.scopes("select")
.authorities("oauth2")
.secret("123456");
八 关于获取token关键类以及断点设置
TokenEndpoint
InMemoryClientDetailsService
CompositeTokenGranter
ClientCredentialsTokenGranter
AbstractTokenGranter
以上就是获取token的关键流程。