文章目录
- DefaultTokenServices
- 实现的接口
- AuthorizationServerTokenServices
- ResourceServerTokenServices
- ConsumerTokenServices
- 代码
- 属性定义
- createAccessToken(OAuth2Authentication)
- createRefreshToken(OAuth2Authentication)
DefaultTokenServices
DefaultTokenServices是掌握spring security oauth2 颁发令牌的重要实现,它有着发放令牌
,存储令牌
,令牌校验
,令牌撤销
等功能;
DefaultTokenServices实现了3个接口:AuthorizationServerTokenServices
、ResourceServerTokenServices
、ConsumerTokenServices
实现的接口
AuthorizationServerTokenServices
授权服务器令牌服务接口
// 创建令牌, 根据 OAuth2Authentication 生成 OAuth2AccessToken 访问令牌对象
OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)// 刷新令牌
OAuth2AccessToken refreshAccessToken(String refreshToken, TokenRequest tokenRequest)// 查询令牌, 查询发放给指定 OAuth2Authentication对象的令牌
OAuth2AccessToken getAccessToken(OAuth2Authentication authentication);
ResourceServerTokenServices
资源服务器令牌服务接口
// 根据令牌 返回 OAuth2Authentication 对象
OAuth2Authentication loadAuthentication(String accessToken)// 根据令牌 获取 访问令牌 对象
OAuth2AccessToken readAccessToken(String accessToken)
ConsumerTokenServices
// 撤销令牌
boolean revokeToken(String tokenValue);
代码
属性定义
public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {// 刷新里令牌的有效期, 默认30天int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // 访问令牌有效期, 默认12小时int accessTokenValiditySeconds = 60 * 60 * 12; // 是否支持刷新令牌boolean supportRefreshToken = false; // 刷新令牌是否可重用boolean reuseRefreshToken = true;// 令牌存储器, 显然, 当前令牌服务把存储令牌的操作和查询令牌的操作交给了TokenStore来处理TokenStore tokenStore;// 客户端服务ClientDetailsService clientDetailsService;// 令牌增强器TokenEnhancer accessTokenEnhancer;// 认证管理器AuthenticationManager authenticationManagerpublic void afterPropertiesSet() throws Exception {// tokenStore不能为空Assert.notNull(tokenStore, "tokenStore must be set");}}
createAccessToken(OAuth2Authentication)
颁发令牌
@Transactional
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) {// 根据 OAuth2Authentication 用户授权信息, 使用 tokenStore 查询 OAuth2AccessToken 访问令牌信息OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);// 刷新令牌OAuth2RefreshToken refreshToken = null;// 如果 查询得到的 OAuth2AccessToken 访问令牌信息 存在if (existingAccessToken != null) {// 如果 查询得到的 OAuth2AccessToken 访问令牌信息 虽然存在, 但是已过期if (existingAccessToken.isExpired()) {// 如果 该过期的 OAuth2AccessToken 访问令牌信息 的刷新令牌 不为空if (existingAccessToken.getRefreshToken() != null) {// 记录已过期的刷新令牌refreshToken = existingAccessToken.getRefreshToken();// 使用 tokenStore 移除此刷新令牌tokenStore.removeRefreshToken(refreshToken);}// 使用 tokenStore 移除 该过期的 OAuth2AccessToken 访问令牌信息tokenStore.removeAccessToken(existingAccessToken);}else {// 查询得到的 OAuth2AccessToken 访问令牌信息 存在, 且没有过期, 将仍然返回此 令牌信息// 在返回前, 重新保存一下 OAuth2AccessToken 令牌信息 和 OAuth2Authentication 用户授权信息tokenStore.storeAccessToken(existingAccessToken, authentication);return existingAccessToken;}}// 如果 前面 未查询到 OAuth2AccessToken 访问令牌信息 // 或是 查询到的 OAuth2AccessToken 访问令牌信息 无 刷新令牌(此时, 令牌信息已过期)if (refreshToken == null) {// 创建刷新令牌refreshToken = createRefreshToken(authentication);}else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {// 前面 查询到的 OAuth2AccessToken 访问令牌信息 的 刷新令牌 类型为 ExpiringOAuth2RefreshToken,ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {// 并且该刷新令牌也已过期, 则也创建刷新令牌refreshToken = createRefreshToken(authentication);}}// 至此, 刷新令牌可以确定了, 并且确定需要创建令牌了// 创建令牌, 传入 OAuth2Authentication 用户授权信息 和 刷新令牌信息(这个刷新令牌信息有肯能是旧的)OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);// 使用 tokenStore 保存 OAuth2AccessToken 令牌信息 和 OAuth2Authentication 用户授权信息 的关系tokenStore.storeAccessToken(accessToken, authentication);// 获取 令牌信息 的刷新令牌 refreshToken = accessToken.getRefreshToken();if (refreshToken != null) {// 如果刷新令牌不为空, 使用 tokenStore 保存 OAuth2RefreshToken 令牌信息 和 OAuth2Authentication 用户授权信息 的关系tokenStore.storeRefreshToken(refreshToken, authentication);}// 返回 令牌信息return accessToken;}
createRefreshToken(OAuth2Authentication)
创建刷新令牌
private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {// 是否支持刷新令牌if (!isSupportRefreshToken(authentication.getOAuth2Request())) {return null;}// 获取 刷新令牌的有效时间int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request());// uuid作为刷新令牌值String value = UUID.randomUUID().toString();// 如果 刷新令牌的有效时间 不为空, 则使用 DefaultExpiringOAuth2RefreshToken 作为刷新令牌的实现,// 并设置 刷新令牌值 和 刷新令牌过期时间if (validitySeconds > 0) {return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis()+ (validitySeconds * 1000L)));}// 如果 刷新令牌的有效时间 为空, 则使用 DefaultOAuth2RefreshToken 作为刷新令牌的实现,// 并设置 刷新令牌值, 没有刷新令牌过期时间return new DefaultOAuth2RefreshToken(value);
}/* 如果有设置 clientDetailsService, 那么查询客户端对应的ClientDetails, 如果该客户端支持刷新令牌,那么直接返回支持, 否则, 由 DefaultTokenServices 的 supportRefreshToken 属性来确定
*/
protected boolean isSupportRefreshToken(OAuth2Request clientAuth) {if (clientDetailsService != null) {ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());return client.getAuthorizedGrantTypes().contains("refresh_token");}return this.supportRefreshToken;
}/* 如果有设置 clientDetailsService, 那么查询客户端对应的ClientDetails, 如果该客户端有设置刷新令牌有效时间,那么直接返回该有效时间, 否则, 由 DefaultTokenServices 的 refreshTokenValiditySeconds 属性来确定
*/
protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) {if (clientDetailsService != null) {ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());Integer validity = client.getRefreshTokenValiditySeconds();if (validity != null) {return validity;}}return refreshTokenValiditySeconds;
}