如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息
Posted
技术标签:
【中文标题】如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息【英文标题】:How to configure Resource Server in Spring Security for it to use additional information in JWT token 【发布时间】:2016-08-29 20:20:11 【问题描述】:我有一个配置为设置有关用户权限的附加信息的 oauth2 jwt 令牌服务器。
@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 注释控制器。
我的 Auth 服务器配置如下所示:
@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");
我的资源服务器配置如下:
@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());
我的测试用例失败得很惨:
"error":"invalid_token","error_description":"无法将访问令牌转换为 JSON"
如何从 JWT 中获取 Authentication 对象? 如何使用客户端凭据对客户端进行身份验证? 如何在我的资源控制器上使用 @Secured 注解?
资源服务器端使用什么代码按顺序解码令牌 提取客户端凭据以及验证用户角色的代码是什么?
请帮忙,因为我已经花了 2 天的时间来解决这个问题 简单的任务。
注意:我从 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]
请解释这些概念并指出我的配置中是否缺少任何内容。我需要知道配置资源和身份验证服务器的最佳做法。
【问题讨论】:
【参考方案1】:下面我指的是我已经成功实现的这个 Baeldung 教程:http://www.baeldung.com/spring-security-oauth-jwt
首先:在 AuthorizationServer 端使用 CustomTokenEnhancer 来使用额外的自定义信息来增强创建的令牌。您应该在 ResourceServer 端使用所谓的 DefaultAccessTokenConverter 来提取这些额外的声明。
您可以将 @Autowire
CustomAccessTokenConverter 放入您的 ResourceServerConfiguration 类,然后将其设置为您的 JwtTokenStore()
配置。
资源服务器配置:
@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,以便在此处提取自定义声明。
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 令牌中的附加信息的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security实现OAuth2.0——资源服务
spring boot整合security 4,怎么设置忽略的静态资源?