Spring Security系列(26)-Spring Security Oauth2之使用令牌增强器TokenEnhancer添加额外信息源码分析及案例

前言

在之前的案例中,认证获取到了访问令牌信息,但是这些信息完全不够,比如没有登录用户名,如果还需要添加其他额外信息应该怎么做呢?
在这里插入图片描述

源码分析

创建令牌

之前我们分析过,DefaultTokenServices在其createAccessToken方法中会进行令牌的创建和存储。

	private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
    
    
		// 1. 使用UUID创建一个默认的令牌
		DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
		// 2. 调用ClientDetailsService 查询令牌的过期时间
		int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
		// 3. 设置令牌的过期时间 Mon Nov 15 10:11:16 CST 2021
		if (validitySeconds > 0) {
    
    
			token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
		}
		// 4. 设置刷新令牌 授权范围
		token.setRefreshToken(refreshToken);
		token.setScope(authentication.getOAuth2Request().getScope());
		// 5. 是否设置了令牌增强,如有则增强后再返回
		return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
	}

可以看到在第5 步骤中,会调用TokenEnhancer接口的enhance方法对令牌进行增强处理。

TokenEnhancer

TokenEnhancer接口位于org.springframework.security.oauth2.provider.token包下,它的主要作用是在令牌存储之前,对令牌进行增强处理,只声明了一个enhance方法。

public interface TokenEnhancer {
    
    

	/**
	 * 增强令牌
	 * 
	 * @param accessToken 当前具有scope及过期时间的访问令牌
	 * @param authentication 当前认证用户信息
	 * @return 添加了额外信息的新令牌
	 */
	OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication);

}

使用案例

1. 实现TokenEnhancer 接口

实现TokenEnhancer 接口,重写enhance方法,该方法传入了OAuth2AccessToken 及OAuth2Authentication 对象,所以可以获取到认证信息,添加到令牌对象中,也可以添加其他额外信息。

public class MyTokenEnhancer implements TokenEnhancer {
    
    

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
    
    
        Map<String, Object> additionalInformation = new HashMap<>();
        // 1. 获取认证信息
        // 客户端
        String clientId = authentication.getOAuth2Request().getClientId();// 客户端ID
        Set<String> resourceIds = authentication.getOAuth2Request().getResourceIds(); // 资源集合
        // 用户
        Authentication userAuthentication = authentication.getUserAuthentication();
        Object principal = userAuthentication.getPrincipal();
        if (principal instanceof User){
    
    
            User user= (User) principal;
            additionalInformation.put("userName", user.getUsername());
        }
        // 2.设置到accessToken中
        additionalInformation.put("resourceIds", resourceIds);
        additionalInformation.put("clientId", clientId);
        additionalInformation.put("deptId", "0001");
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
        return accessToken;
    }
}

2. 添加配置

在AuthorizationServer配置类中声明TokenEnhancer Bean对象,然后在端点配置类中添加令牌增强器。

    // 端点配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    
        // 配置端点允许的请求方式
        endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
        // 配置认证管理器
        endpoints.authenticationManager(authenticationManager);
        // 自定义异常翻译器,用于处理OAuth2Exception
        endpoints.exceptionTranslator(myWebResponseExceptionTranslator);
        // 重新组装令牌颁发者,加入自定义授权模式
        endpoints.tokenGranter(getTokenGranter(endpoints));
/*      // 添加JWT令牌
        // JWT令牌转换器
        endpoints.accessTokenConverter(jwtAccessTokenConverter);
        // JWT 存储令牌*/
        endpoints.tokenStore(redisTokenStore);
        // 刷新令牌模式添加 userDetailsService
        endpoints.userDetailsService(userDetailsService);
        // 添加令牌增强器
        endpoints.tokenEnhancer(tokenEnhancer());
    }
     @Bean
    public TokenEnhancer tokenEnhancer() {
    
    
        return new MyTokenEnhancer();
    }

3. 测试

访问令牌端点,发现返回了自定义的额外信息。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43437874/article/details/121328682