如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息 [英] How to configure Resource Server in Spring Security for it to use additional information in JWT token

查看:42
本文介绍了如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个配置为设置有关用户权限的附加信息的 oauth2 jwt 令牌服务器.

I have an oauth2 jwt token server configured to set additional info about the user authorities.

@Configuration
@Component
public class CustomTokenEnhancer extends JwtAccessTokenConverter {

    CustomTokenEnhancer(){
        super();
    }

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        // TODO Auto-generated method stub
        MyUserDetails user = (MyUserDetails) authentication.getPrincipal();
        final Map<String, Object> additionalInfo = new HashMap<>();
        @SuppressWarnings("unchecked")
        List<GrantedAuthority> authorities= (List<GrantedAuthority>) user.getAuthorities();
        additionalInfo.put("authorities", authorities);

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

        return accessToken;
    }

}

我不确定如何配置我的资源服务器以提取由 oauth2 服务器设置的用户权限,并将该权限用于 Spring Security 框架中的 @Secured 注释控制器.

I am not sure how to configure my resource server to extract the user authorities set by the oauth2 server and use that authority to be used for @Secured annotated controllers in Spring Security framework.

我的 Auth 服务器配置如下所示:

My Auth server configuration looks like this:

@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Value("${config.oauth2.privateKey}")
    private String privateKey;

    @Value("${config.oauth2.publicKey}")
    private String publicKey;

    @Value("{config.clienturl}")
    private String clientUrl;

    @Autowired
    AuthenticationManager authenticationManager;

    @Bean
    public JwtAccessTokenConverter customTokenEnhancer(){

        JwtAccessTokenConverter customTokenEnhancer = new CustomTokenEnhancer();
        customTokenEnhancer.setSigningKey(privateKey);

        return customTokenEnhancer;
    }

    @Bean
    public JwtTokenStore tokenStore() {
        return new JwtTokenStore(customTokenEnhancer());
    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .tokenKeyAccess("isAnonymous() || hasRole('ROLE_TRUSTED_CLIENT')") // permitAll()
                .checkTokenAccess("hasRole('TRUSTED_CLIENT')"); // isAuthenticated()
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints


        .authenticationManager(authenticationManager)
        .tokenStore(tokenStore())
        .accessTokenConverter(customTokenEnhancer())
;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        String url = clientUrl;

        clients.inMemory()


        .withClient("public") 
        .authorizedGrantTypes("client_credentials", "implicit")
        .scopes("read")
        .redirectUris(url)

        .and()


        .withClient("eagree_web").secret("eagree_web_dev")
        //eagree_web should come from properties file?
        .authorities("ROLE_TRUSTED_CLIENT") 
        .authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token")
        .scopes("read", "write", "trust") 
        .redirectUris(url).resourceIds("dummy");
    }
}

我的资源服务器配置如下:

And my Resource Server configuration looks like this:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter {



    @Value("{config.oauth2.publicKey}")
    private String publicKey;

    @Autowired
    CustomTokenEnhancer tokenConverter;

    @Autowired
    JwtTokenStore jwtTokenStore;

    @Bean
    public JwtTokenStore jwtTokenStore() {
        tokenConverter.setVerifierKey(publicKey);
        jwtTokenStore.setTokenEnhancer(tokenConverter);
        return jwtTokenStore;
    }

    @Bean
    public ResourceServerTokenServices defaultTokenServices() {
        final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenEnhancer(tokenConverter);
        defaultTokenServices.setTokenStore(jwtTokenStore());
        return defaultTokenServices;
    }


    @Override
    public void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // @formatter:off
        http
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
                .and()
                .requestMatchers()
                .antMatchers("/**")
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.PATCH, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers("/admin/**").access("hasRole('ROLE_USER')");

        // @formatter:on
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        System.out.println("Configuring ResourceServerSecurityConfigurer ");
        resources.resourceId("dummy").tokenServices(defaultTokenServices());
    }

}

我的测试用例失败得很惨:

My test case is failing miserably saying:

{"error":"invalid_token","error_description":"无法将访问令牌转换为 JSON"}

{"error":"invalid_token","error_description":"Cannot convert access token to JSON"}

如何从 JWT 中获取 Authentication 对象?如何使用客户端凭据对客户端进行身份验证?如何在我的资源控制器上使用 @Secured 注解?

How do I get the Authentication object out of the JWT? How do I authenticate the client, with client credentials? How do I use @Secured annotation on my resource controllers?

资源服务器端使用什么代码按顺序解码令牌提取客户端凭据以及验证用户角色的代码是什么?

What code is used on the resource server side to decode the token in order to extract client credentials and what code gets to user role verified?

请帮忙,因为我已经花了 2 天的时间来解决这个问题简单的任务.

Please help, as I already spent 2 days banging my head on this seemingly easy task.

注意:我从 Auth 服务器接收令牌:{access_token=b5d89a13-3c8b-4bda-b0f2-a6e9d7b7a285, token_type=bearer, refresh_token=43777224-b6f2-44d7-bf36-4e1934d32cbb, expires_in=43199, scope=read write trust, authority=[{authority=ROLE_USER}, {authority=ROLE_ADMIN}]}

Note: I receive the token from Auth server as: {access_token=b5d89a13-3c8b-4bda-b0f2-a6e9d7b7a285, token_type=bearer, refresh_token=43777224-b6f2-44d7-bf36-4e1934d32cbb, expires_in=43199, scope=read write trust, authorities=[{authority=ROLE_USER}, {authority=ROLE_ADMIN}]}

请解释这些概念并指出我的配置中是否缺少任何内容.我需要知道配置资源和身份验证服务器的最佳做法.

Please explain the concepts and point out if anything is missing from my configuration. I need to know the best practices in configuring my resource and auth server please.

推荐答案

下面我指的是我已经成功实现的这个Baeldung教程:http://www.baeldung.com/spring-security-oauth-jwt

In the following I'm referring to this Baeldung tutorial that I already implemented successfully: http://www.baeldung.com/spring-security-oauth-jwt

首先:在 AuthorizationServer 端使用 CustomTokenEnhancer 来使用额外的自定义信息来增强创建的令牌.您应该在 ResourceServer 端使用所谓的 DefaultAccessTokenConverter 来提取这些额外的声明.

First at all: The CustomTokenEnhancer is used on the AuthorizationServer side to enhance a created token with additional custom information. You should use the so called DefaultAccessTokenConverter on the ResourceServer side to extract these extra claims.

您可以将 CustomAccessTokenConverter @Autowire 放入您的 ResourceServerConfiguration 类,然后将其设置为您的 JwtTokenStore() 配置.

You can @Autowire the CustomAccessTokenConverter into your ResourceServerConfiguration class and then set it to your JwtTokenStore() configuration.

资源服务器配置:

@Autowired
private CustomAccessTokenConverter yourCustomAccessTokenConverter;

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

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setAccessTokenConverter(yourCustomAccessTokenConverter);
    converter.setSigningKey(yourSigningKey);
    return converter;
}

可以配置 CustomAccessTokenConverter,以便在此处提取自定义声明.

The CustomAccessTokenConverter can be configured, so that the custom claims get extracted here.

CustomAccessTokenConverter:

@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
        OAuth2Authentication authentication = super.extractAuthentication(claims);
        authentication.setDetails(claims);
        return authentication;
    }

}

(参见:https://github.com/Baeldung/spring-security-oauth/blob/master/oauth-resource-server-1/src/main/java/org/baeldung/config/CustomAccessTokenConverter.java)

这篇关于如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆