版权声明:本文为博主ExcelMann的原创文章,未经博主允许不得转载。
作者:ExcelMann,转载需注明。
一、SpringSecurity以及OAuth2源码分析
我们先来看下通过OAuth2获取token的源码流程:
一、获取token的接口是/oauth/token,在TokenEndpoint类中
public class TokenEndpoint extends AbstractEndpoint {
@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");
}
return postAccessToken(principal, parameters);
}
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
...
}
}
其中第一个接口是Get请求,第二个接口是Post请求,Get请求实质上最后也是调用Post请求的方法。
二、在postAccessToken
方法中,其中最主要的代码是第132行
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
调用TokenEndpoint父类AbstractEndpoint的getTokenGranter()
方法获取端点endpoint的tokenGranter,并调用granter的grant
方法。
三、AuthorizationServerEndpointsConfigurer认证服务端点配置器
在上一句代码中,点击grant,可以发现该认证服务端点配置器。
这个认证服务端点配置器是我们在AuthorizationServerConfig
认证服务配置器中,其中一个configure()
重载方法,该方法的参数就是认证服务端点配置器(后续若新增自定义GrantType的话,需要在上述的认证服务配置器中的endpoint配置):
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
...}
而认证服务端点配置器中,有以下两个方法,是关于TokenGranter的初始化
private TokenGranter tokenGranter() {
if (this.tokenGranter == null) {
this.tokenGranter = new TokenGranter() {
private CompositeTokenGranter delegate;
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (this.delegate == null) {
this.delegate = new CompositeTokenGranter(AuthorizationServerEndpointsConfigurer.this.getDefaultTokenGranters());
}
return this.delegate.grant(grantType, tokenRequest);
}
};
}
return this.tokenGranter;
}
private List<TokenGranter> getDefaultTokenGranters() {
ClientDetailsService clientDetails = this.clientDetailsService();
AuthorizationServerTokenServices tokenServices = this.tokenServices();
AuthorizationCodeServices authorizationCodeServices = this.authorizationCodeServices();
OAuth2RequestFactory requestFactory = this.requestFactory();
List<TokenGranter> tokenGranters = new ArrayList();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails, requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
tokenGranters.add(implicit);
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
if (this.authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(this.authenticationManager, tokenServices, clientDetails, requestFactory));
}
return tokenGranters;
}
其中tokenGranter()
方法创建了一个CompositeTokenGranter类对象,并调用getDefaultTokenGranters()
方法,将默认的几种TokenGranter作为CompositeTokenGranter类对象的构造方法参数,添加到CompositeTokenGranter类的tokenGranters列表中。
四、CompositeTokenGranter
在这个TokenGranter中,由上述可知,存有默认的所有TokenGranter作为类的属性变量。
public class CompositeTokenGranter implements TokenGranter {
private final List<TokenGranter> tokenGranters;
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
for (TokenGranter granter : tokenGranters) {
OAuth2AccessToken grant = granter.grant(grantType, tokenRequest);
if (grant!=null) {
return grant;
}
}
return null;
}
public void addTokenGranter(TokenGranter tokenGranter) {
if (tokenGranter == null) {
throw new IllegalArgumentException("Token granter is null");
}
tokenGranters.add(tokenGranter);
}
而其中grant()
方法,具体就是遍历所有的granter,并调用当前granter的grant方法,得到的结果若不为空则返回。
其中的addTokenGranter()
方法就是添加新的TokenGranter的方法。
五、AbstractTokenGranter
这个类是实现TokenGranter接口的一个抽象类,该类实现了TokenGranter接口的方法,并且其他的TokenGranter都是基于这个类来拓展(就可以不需要重新实现TokenGranter接口的大多数方法)。
比如:ClientCredentialsTokenGranter,就是在AbstractTokenGranter的基础上拓展的一个新的TokenGranter。
public class ClientCredentialsTokenGranter extends AbstractTokenGranter {
private static final String GRANT_TYPE = "client_credentials";
...
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
OAuth2AccessToken token = super.grant(grantType, tokenRequest);
if (token != null) {
DefaultOAuth2AccessToken norefresh = new DefaultOAuth2AccessToken(token);
// The spec says that client credentials should not be allowed to get a refresh token
if (!allowRefresh) {
norefresh.setRefreshToken(null);
}
token = norefresh;
}
return token;
}
}
仔细分析grant方法可以发现,其实调用的还是父类(AbstractTokenGranter)的grant方法。
父类的grant方法如下:
public OAuth2AccessToken grant(String grantType