【问题标题】:Adding User data to the JWT payload for spring security OAUth2将用户数据添加到 Spring Security OAUth2 的 JWT 有效负载
【发布时间】:2017-02-17 20:42:14
【问题描述】:

一段时间以来,我一直在使用使用 JWT 令牌的 Spring Security OAuth2,但现在我需要向 JWT 令牌添加 2 个用户定义的值。

所以当我向请求添加一组额外的参数时 /oauth/token?grant_type=client_credentials&user_value=1234567890。

上面的 user_value 用于演示目的。我可以将它一直追踪到我的 CustomTokenEnhancer 中(我将其连接为一直传递此信息的一种方式)。所有请求参数都可以通过传递给我的 CustomTokenEnhancer 的 OAuth2Authentication 身份验证看到。

现在我可以将此信息添加到作为令牌请求的一部分返回给我的附加信息中。见下文。

{
   "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicGhpLWFwaSJdLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwib3JnYW5pemF0aW9uIjoicGhpLXVzZXJtZ3RuIiwidXNlcl90b2tlbiI6IjEyMzQ1Njc4OTAiLCJleHAiOjE0ODczNjc2NzEsImF1dGhvcml0aWVzIjpbIlJPTEVfQ0xJRU5UIl0sImp0aSI6IjFlZDMzZTAxLTc1ZGUtNDNjZC1hMzk2LTFkMzk2N2Y1NDQ5OCIsImNsaWVudF9pZCI6InBoaS11c2VyIn0.p628BNaaGljypEcGXZMkstNeTN-221qzzNQQ0npxDLTszWaXkgXqsBnBbKf9XMEtWTeCQkIszC9ne1Ei2X5IWTskhLT9Rko-8K7Jq-mXUc6HJZW-3tGV5rRer8Eyyw1wysW9Jiyp7sPkN-TIx12A70f_LHm6PrRR4ECppHWADs-2DvYA30p8omT1_RTt2WlqC40mopUN2TBPkb1WulVpOUEpcP358Ox8oVP8VQRSkLGZKB_b0KZAK9KGjLg6WNh8RghZaBuYuJQpITe_0XEBs_JfwrHhcK1IGaoYwSS7IGp3Cima9OMljdzayDKRqlfSl3WhaBuFmD1S37p-OVQL0A",
   "token_type":"bearer",
   "expires_in":8967,
   "scope":"read write",
   "user_value":"1234567890",
   "jti":"1ed33e01-75de-43cd-a396-1d3967f54498"
}

但我不希望这些值以这种方式可见。我希望将它们添加到加密令牌中。

我花了一些时间寻找,但不清楚我实际上是如何添加的。这应该是可能的,不是吗?

【问题讨论】:

    标签: spring-security-oauth2


    【解决方案1】:

    在您自己的 TokenEnhancer 中,您必须再次对其进行编码:

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        // Generate additional Information [...]
    
    
        // Write it to the token
        ((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(addInfo);
    
        // Encode Token to JWT
        String encoded = super.encode(accessToken, authentication);
    
        // Set JWT as value of the token
        ((DefaultOAuth2AccessToken) accessToken).setValue(encoded);
    
        return accessToken;
    }
    

    你可以使用JwtHelper 方法解决这个问题,但我只是扩展了JwtAccessTokenConverter,所以我可以只使用编码和解码。

    在实例化你的令牌增强器时,你必须添加密钥库信息:

    private CustomTokenEnhancer jwtCustomEnhancer() {
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "***".toCharArray());
        CustomTokenEnhancer converter = new CustomTokenEnhancer();
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("jwt"));
    
        return converter;
    }
    

    【讨论】:

      【解决方案2】:

      在用户详细信息服务(而不是令牌增强器)的帮助下,我做了类似的事情,将值作为授予的权限传递。在客户端,我编写了一个提取器来从 spring 注入的主体中检索值作为 OAuth2Authentication 类型。以下代码在 Scala 中,但您可以轻松适应 Java:

      /**
        * Mix-in to implicitly extract entity or identity from the principal.
        */
      trait AuthorityExtractor {
      
        def _contextName(implicit principal: OAuth2Authentication) = id(principal, "CONTEXT_")
      
        def _entityId(implicit principal: OAuth2Authentication) = id(principal, "ENTITY_ID_")
      
        def _userId(implicit principal: OAuth2Authentication) = id(principal, "USER_ID_")
      
        def _identityId(implicit principal: OAuth2Authentication) = id(principal, "SELF_ID_")
      
        private def id(principal: OAuth2Authentication, prefix: String) = {
          import collection.JavaConversions._
          principal
            .getAuthorities
            .filter(_.toString.startsWith(prefix))
            .map(_.toString.substring(prefix.length))
            .headOption.getOrElse("")
        }
      
      }

      【讨论】:

        【解决方案3】:

        我像这样扩展JwtAccessTokenConverter 类:

        public class FooJwtAccessTokenConverter extends JwtAccessTokenConverter {
          @Override
          public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
             DefaultOAuth2AccessToken fooAccessToken = new DefaultOAuth2AccessToken(accessToken);
             fooAccessToken.getAdditionalInformation().put("foo_property", "foo");
             return super.enhance(scaAccessToken, authentication);
          }
        

        在我的 AuthotizationServerConfig 中,我创建了这个:

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .tokenStore(tokenStore())
                    .accessTokenConverter(accessTokenConverter())
                    .authenticationManager(authenticationManager);
        }
        
        @Bean
        public TokenStore tokenStore() {
            return new JwtTokenStore(accessTokenConverter());
        }
        
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            ScaJwtAccessTokenConverter accessTokenConverter = new ScaJwtAccessTokenConverter();
            accessTokenConverter.setSigningKey("familia-mgpe"); // Parte da string de validação do token JWT.
            return accessTokenConverter;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-07-09
          • 2016-05-03
          • 1970-01-01
          • 2023-04-07
          • 2020-12-26
          • 2015-09-05
          • 2017-02-08
          • 2016-03-12
          • 2017-10-24
          相关资源
          最近更新 更多