TokenEnhancerChain 是 Spring Security OAuth2(旧版,已弃用) 中用于组合多个 TokenEnhancer 的一个工具类。它的核心作用是:在生成 Access Token(访问令牌)的过程中,按顺序应用多个增强器(enhancer),以自定义令牌的内容。
在默认情况下,OAuth2 授权服务器生成的 JWT Token 只包含标准字段(如 exp, iat, scope, client_id 等)。但实际业务中,我们常常需要: 将用户ID、用户名、角色、部门等信息写入 Token; 添加自定义业务字段(如租户ID、会员等级); 对 Token 进行签名前的最后处理。 这就需要用到 TokenEnhance
✅ 定义 TokenEnhancer 是一个接口,允许你在 Token 被最终签名/序列化之前,修改其内容(即 OAuth2AccessToken 对象)。
public interface TokenEnhancer {
OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication);
} accessToken:即将返回的 Token 对象 authentication:当前认证信息(包含用户详情、客户端信息等) 🌰 自定义增强器示例
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
// 从 authentication 中获取用户信息
if (authentication.getUserAuthentication() != null) {
User user = (User) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put("user_id", user.getId());
additionalInfo.put("username", user.getUsername());
additionalInfo.put("authorities", user.getAuthorities());
}
// 将自定义信息添加到 token 的额外信息中
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}✅ 问题场景 你可能有多个增强逻辑: 一个增强器负责加用户信息; 一个增强器负责加审计字段(如 issued_at); 一个增强器负责加租户上下文。 如果手动嵌套调用,代码会很丑:
token = enhancer1.enhance(token, auth);
token = enhancer2.enhance(token, auth);
token = enhancer3.enhance(token, auth);✅ 解决方案:TokenEnhancerChain 它实现了 TokenEnhancer 接口,并内部维护一个 List<TokenEnhancer>,按顺序调用每个增强器。 🔧 使用方式(在授权服务器配置中)
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter())
.tokenEnhancer(tokenEnhancerChain()); // ← 注入链
}
@Bean
public TokenEnhancerChain tokenEnhancerChain() {
TokenEnhancerChain chain = new TokenEnhancerChain();
chain.setTokenEnhancers(Arrays.asList(
new CustomUserTokenEnhancer(), // 增强用户信息
new AuditTokenEnhancer(), // 增强审计信息
jwtAccessTokenConverter() // 注意:JWT转换器本身也是一个TokenEnhancer!
));
return chain;
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("my-secret-key");
return converter;
}
}⚠️ 关键点: JwtAccessTokenConverter 本身也实现了 TokenEnhancer 接口! 所以在使用 JWT 时,必须把它放在 TokenEnhancerChain 的最后,因为它负责最终的签名和序列化。 四、执行顺序与注意事项 🔁 执行流程 当调用 /oauth/token 时: 授权服务器生成原始 Token; 调用 TokenEnhancerChain.enhance(); 链中每个 TokenEnhancer 按顺序修改 accessToken; 最后由 JwtAccessTokenConverter 签名并生成 JWT 字符串。 ⚠️ 重要注意事项 表格 问题 说明 顺序很重要 先加业务字段,再签名。如果 JwtAccessTokenConverter 不在最后,后续增强器的修改不会被签入 JWT! 只影响 Access Token TokenEnhancer 不处理 Refresh Token(除非你显式处理) 仅适用于 JWT 或自定义 TokenStore 如果用 InMemoryTokenStore,增强的信息会存储在内存中;但如果是 JWT,信息会被编码进 Token 本身 安全性 不要往 Token 里放敏感信息(如密码、身份证号),因为 JWT 可被解码(虽然不能篡改) 五、现代替代方案(Spring Authorization Server) 在新版 Spring Authorization Server 中: 不再有 TokenEnhancer 或 TokenEnhancerChain 自定义 Token 内容通过 OAuth2TokenCustomizer<JwtEncoder> 实现
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() {
return context -> {
if (context.getTokenType().equals(OAuth2TokenType.ACCESS_TOKEN)) {
// 获取认证信息
Authentication principal = context.getPrincipal();
if (principal instanceof JwtAuthenticationToken) {
// 处理 JWT 认证
} else if (principal.getPrincipal() instanceof UserDetails) {
UserDetails user = (UserDetails) principal.getPrincipal();
// 添加自定义 claim
context.getHeaders().header("custom-header", "value");
context.getClaims().claim("user_name", user.getUsername());
context.getClaims().claim("authorities", user.getAuthorities());
}
}
};
}✅ 新方案更符合 Spring Security 原生模型,类型安全,且与 OAuth 2.1 标准对齐。 六、总结 表格 概念 作用 状态 TokenEnhancer 单个 Token 内容增强器 旧版(已弃用) TokenEnhancerChain 组合多个增强器,按顺序执行 旧版(已弃用) 核心用途 在 Token 签名前注入自定义信息(用户ID、角色等) — 现代替代 OAuth2TokenCustomizer<JwtEncodingContext> 推荐新项目使用 💡 记住: 如果你在维护旧系统,TokenEnhancerChain 是向 JWT 中添加业务信息的标准方式; 如果你在开发新系统,请直接使用 Spring Authorization Server 的 OAuth2TokenCustomizer。 理解 TokenEnhancerChain 的本质——责任链模式在 Token 生成过程中的应用——有助于你掌握 OAuth2 令牌的定制化能力。