额外的声明不会通过自定义 TokenEnhancer 添加到 JWT 有效负载

Posted

技术标签:

【中文标题】额外的声明不会通过自定义 TokenEnhancer 添加到 JWT 有效负载【英文标题】:Extra claim doesn't add to JWT payload by custom TokenEnhancer 【发布时间】:2018-08-07 11:04:07 【问题描述】:

我创建了一些 TokenEnhancer 来为 JWT 添加额外的声明:

@Component
public class TestTokenEnhancer implements TokenEnhancer 

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) 

        final Map<String, Object> additionalJwtProperties = ImmutableMap
                .<String, Object>builder()
                .put("testProperty", "testValue")
                .build();

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalJwtProperties);

        return accessToken;
    

然后我已经配置了我的授权服务器,一个:

@Configuration
public class TokenConfig 

    private List<TokenEnhancer> tokenEnhancers;

    @Autowired
    public void setTokenEnhancers(List<TokenEnhancer> tokenEnhancers) 
        this.tokenEnhancers = tokenEnhancers;
    

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() 
        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("test123");
        return converter;
    

    @Bean
    public TokenStore tokenStore() 
        return new JwtTokenStore(accessTokenConverter());
    

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() 
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    

    @Bean
    public TokenEnhancerChain tokenEnhancerChain() 
        TokenEnhancerChain chain = new TokenEnhancerChain();
        chain.setTokenEnhancers(allTokenEnhancers());
        return chain;
    

    private List<TokenEnhancer> allTokenEnhancers() 
        TokenEnhancer[] restTokenEnhancers = this.tokenEnhancers.toArray(new TokenEnhancer[this.tokenEnhancers.size()]);
        return Lists.asList(accessTokenConverter(), restTokenEnhancers);
    

还有两个:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 

    private AuthenticationManager authenticationManager;
    private TokenStore tokenStore;
    private TokenEnhancerChain tokenEnhancerChain;

    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) 
        this.authenticationManager = authenticationManager;
    

    @Autowired
    public void setTokenStore(TokenStore tokenStore) 
        this.tokenStore = tokenStore;
    

    @Autowired
    public void setTokenEnhancerChain(TokenEnhancerChain tokenEnhancerChain) 
        this.tokenEnhancerChain = tokenEnhancerChain;
    

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception  // @formatter:off
        clients.inMemory()
          .withClient("client-example")
          .secret("client-secret")
          .authorizedGrantTypes("password")
          .scopes("message-service")
          .autoApprove(true);
     // @formatter:on

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)  // @formatter:off
        endpoints
          .tokenStore(this.tokenStore)
          .authenticationManager(this.authenticationManager)
          .tokenEnhancer(this.tokenEnhancerChain);
     // @formatter:on

当我从授权服务器请求访问令牌时,它会使用以下 json 响应我:


  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MTk3OTU0NTAsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiODc5NGI1MmUtZTE4NC00MTJiLWIzOTQtYzY0MTBjN2Q4N2QyIiwiY2xpZW50X2lkIjoiY2xpZW50LWV4YW1wbGUiLCJzY29wZSI6WyJtZXNzYWdlLXNlcnZpY2UiXX0.d2P-Z-SBkoH3ktckVWwW7CvHQXIeqxFvWr_far-dzuo",
  "token_type": "bearer",
  "expires_in": 43200,
  "scope": "message-service",
  "testProperty": "testValue"

我在获得的 json 中看到“testProperty”,但是当我获取“access_token”属性的值并通过jwt.io 检查其内容时,JWT 有效负载中的“testProperty”不存在。这是正确的行为吗?

【问题讨论】:

【参考方案1】:

TokenEnhancerChain 对象的tokenEnhancers 列表末尾添加JwtAccessTokenConverter 很重要。

private List<TokenEnhancer> allTokenEnhancers() 
    return ImmutableList
            .<TokenEnhancer>builder()
            .addAll(this.tokenEnhancers)
            .add(accessTokenConverter())
            .build();

否则,在应用 JwtAccessTokenConverter 后,由另一个 TokenEnhancers 添加的所有额外声明将不会添加到 JWT 的有效负载部分。

【讨论】:

以上是关于额外的声明不会通过自定义 TokenEnhancer 添加到 JWT 有效负载的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法通过自定义事件传递额外的数据?

使用 django-allauth 额外数据添加自定义用户

如何将额外的参数传递给 django admin 自定义表单?

Qt:QScrollArea 中的自定义小部件

如何将额外参数传递给链接到 XIB 文件的自定义 UIView?

Gradle —— 添加自定义 Property