如何将oauth_client_details的additional_information数据存入JWT
嘿,我完全懂你的困扰!之前我也折腾过这个——明明JdbcClientDetailsService已经把additional_information的JSON解析好了,却不知道怎么把它塞进JWT里。别担心,下面几步就能搞定:
把客户端
additional_information存入JWT的步骤 核心思路是扩展Spring Security OAuth2的Token增强器,让它在生成JWT时主动把客户端的额外信息添加进去。
1. 自定义TokenEnhancer类
这个类的作用就是在Token生成过程中,把客户端详情里的additional_information追加到JWT的Claims中:
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import java.util.Map; public class ClientAdditionalInfoTokenEnhancer implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { // 从认证信息里拿到客户端详情 Object clientDetails = authentication.getOAuth2Request().getClientDetails(); if (clientDetails instanceof BaseClientDetails) { BaseClientDetails details = (BaseClientDetails) clientDetails; // 直接拿已经解析好的额外信息(JdbcClientDetailsService已经帮我们转成Map了) Map<String, Object> additionalInfo = details.getAdditionalInformation(); // 把这些信息塞进Token的额外字段里 ((DefaultOAuth2AccessToken) accessToken).getAdditionalInformation().putAll(additionalInfo); } return accessToken; } }
2. 把自定义增强器配置到授权服务器
接下来要让这个增强器参与到Token生成流程里,需要在你的授权服务器配置类里做如下修改:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import java.util.ArrayList; import java.util.List; @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // 这些依赖根据你自己的项目配置注入,比如TokenStore、JWT转换器、JdbcClientDetailsService private final TokenStore tokenStore; private final JwtAccessTokenConverter jwtAccessTokenConverter; private final JdbcClientDetailsService jdbcClientDetailsService; public AuthorizationServerConfig(TokenStore tokenStore, JwtAccessTokenConverter jwtAccessTokenConverter, JdbcClientDetailsService jdbcClientDetailsService) { this.tokenStore = tokenStore; this.jwtAccessTokenConverter = jwtAccessTokenConverter; this.jdbcClientDetailsService = jdbcClientDetailsService; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // 使用我们的JDBC客户端详情服务 clients.withClientDetails(jdbcClientDetailsService); } // 注册自定义的Token增强器Bean @Bean public TokenEnhancer clientAdditionalInfoTokenEnhancer() { return new ClientAdditionalInfoTokenEnhancer(); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // 构建Token增强器链,把自定义增强器和JWT转换器都加进去 TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); List<TokenEnhancer> enhancers = new ArrayList<>(); enhancers.add(clientAdditionalInfoTokenEnhancer()); enhancers.add(jwtAccessTokenConverter); enhancerChain.setTokenEnhancers(enhancers); // 把增强器链配置到端点上 endpoints.tokenStore(tokenStore) .accessTokenConverter(jwtAccessTokenConverter) .tokenEnhancer(enhancerChain); } }
3. 验证效果
现在重新生成JWT Token,用解析工具(比如本地的JWT解析类或者在线工具)查看Payload,就能看到special-id: "abc-123"已经被包含进去了!
额外提醒
- 不用自己再解析JSON:
JdbcClientDetailsService.loadClientByClientId已经把additional_information字段从JSON字符串转成了Map<String, Object>,所以我们直接调用getAdditionalInformation()就能用。 - 敏感数据要注意:JWT是Base64编码的,不是加密的,所以别把敏感信息放到
additional_information里,否则任何人都能解析看到。
内容的提问来源于stack exchange,提问作者Arthur
相关产品推荐
相关产品推荐

