如何使用资源服务器中授权服务器中的jdbc令牌存储访问添加到令牌的自定义声明?

时间:2019-07-23 18:14:57

标签: spring spring-boot spring-security-oauth2

我已使用TokenEnhancer在令牌中添加了自定义声明,我需要在Principal和/或身份验证对象中提供一些自定义声明。

我正在使用JdbcTokenStore,而不是JwtTokenStore。

我浏览了一些论坛和文章,但是大多数谈论JwtTokenStore,而不是JdbcTokenStore。

public class AuthTokenEnhancer implements TokenEnhancer {

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

        Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put("claim1", "claimVal");
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
        return accessToken;
    }

}

2 个答案:

答案 0 :(得分:0)

您的问题内有答案。

JWT用于安全地表示两方之间的索偿 。没有JWT,就不会有索赔的问题。

这意味着如何将声明添加到普通令牌中,并期望资源服务器可以读取它。该令牌增强器将向客户端提供附加信息,并且不会存储到任何数据库中,因此资源服务器无法知道它。

针对您的案例,最简单的解决方案是使用JWT。但是,如果它是敏感信息,也许您应该将其存储在数据库中,并通过API进行公开,该API将检查用户访问它的权限。

答案 1 :(得分:0)

基本上,您可以:

  1. 在AuthorizationServer上:提供您的自定义TokenEnhancer 实施并通过AuthorizationServerConfigurer
  2. 对其进行配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenEnhancer(tokenEnhancer());
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new TestTokenEnhancer();
    }

}
  1. 在ResourceServer上:扩展DefaultUserAuthenticationConverter并覆盖extractAuthentication,在其中您可以从Map中读取自定义声明,并将其添加到Authentication(或您自己的扩展名)中的)。
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    RemoteTokenServices tokenServices;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenServices(testTokenServices());
    }

    private ResourceServerTokenServices testTokenServices() {
        tokenServices.setAccessTokenConverter(testAccessTokenConverter());
        return tokenServices;
    }

    private AccessTokenConverter testAccessTokenConverter() {
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(testUserTokenConverter());
        return accessTokenConverter;
    }

    /**
     * Retrieve additional claims that were set in the TokenEnhancer of the Authorization server during Oauth token creation.
     */
    private UserAuthenticationConverter testUserTokenConverter() {

        return new DefaultUserAuthenticationConverter() {

            @Override
            public Authentication extractAuthentication(Map<String, ?> map) {
                Authentication authentication = super.extractAuthentication(map);

                if (authentication != null) {
                    authentication = new TestAuthenticationToken(authentication.getPrincipal(),
                            authentication.getCredentials(), authentication.getAuthorities(),
                            (String) map.get("testKey"));
                }

                return authentication;
            }
        };

    }

}

This thread包含相关解决方案。

在开发迭代期间,请不要忘记从数据库(表oauth_access_token)中删除令牌!否则,您将获得一个不反映您当前的自定义声明的“旧”(未过期)令牌。