如何在 access_token JWT 中添加更多数据
Posted
技术标签:
【中文标题】如何在 access_token JWT 中添加更多数据【英文标题】:How to add more data in access_token JWT 【发布时间】:2018-08-31 17:44:06 【问题描述】:我正在尝试在 JWT 令牌中添加新字段,它实际上是 access_token
,它是由 grant_type=password
生成的。如果授权类型仅为password
,我想添加更多字段。
如果我实现了自定义令牌增强器,它会在 oauth login api 的响应正文中添加新字段。但我只需要access_token
JWT 中的那些新字段。
例如:
解码access_token
时,Object应该来自
"user_name": "uuid",
"scope": [
"trust"
],
"exp": 1522008499,
"authorities": [
"USER"
],
"jti": "9d827f63-99ba-4fc1-a838-bc74331cf660",
"client_id": "myClient"
到
"user_name": "uuid",
"newField": [
"newFieldChild": "1",
,
"newFieldChild": "2",
],
"scope": [
"trust"
],
"exp": 1522008499,
"authorities": [
"USER"
],
"jti": "9d827f63-99ba-4fc1-a838-bc74331cf660",
"client_id": "myClient"
实现CustomTokenEnhancer
在登录的响应体中添加newField
列表:
"access_token": "jwt-access_token",
"token_type": "bearer",
"refresh_token": "jwt-refresh_token",
"expires_in": 299999,
"scope": "trust",
"jti": "b23affb3-39d3-408a-bedb-132g6de15d7",
"newField": [
"newFieldChild": "1",
,
"newFieldChild": "2",
]
CustomTokenEnhancer
:
public class CustomTokenEnhancer implements TokenEnhancer
@Override
public OAuth2AccessToken enhance(
OAuth2AccessToken accessToken,
OAuth2Authentication authentication)
Map<String, Object> additionalInfo = new HashMap<>();
Map<String, String> newFields = ....;
additionalInfo.put("newField", newFields);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
如果grant_type
是password
,是否可以修改access_token
JWT?
【问题讨论】:
Spring OAuth 2 + JWT Inlcuding additional info JUST in access token的可能重复 【参考方案1】:您的问题与下面的 SO 线程非常相似/相同
Spring OAuth 2 + JWT Inlcuding additional info JUST in access token
我会让它更容易理解。有两件事
访问令牌增强器可增强您的令牌以包含更多信息 一个令牌转换器,可将令牌转换为您在 API 中看到的输出所以你想要的就在下面
访问令牌增强器应该看到其他属性 访问令牌转换器不应看到其他属性下面是我实际使用的类
package org.baeldung.config;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfigJwt extends AuthorizationServerConfigurerAdapter
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("sampleClientId")
.authorizedGrantTypes("implicit")
.scopes("read", "write", "foo", "bar")
.autoApprove(false)
.accessTokenValiditySeconds(3600)
.and()
.withClient("fooClientIdPassword")
.secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("foo", "read", "write")
.accessTokenValiditySeconds(3600)
// 1 hour
.refreshTokenValiditySeconds(2592000)
// 30 days
.and()
.withClient("barClientIdPassword")
.secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("bar", "read", "write")
.accessTokenValiditySeconds(3600)
// 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
;
@Bean
@Primary
public DefaultTokenServices tokenServices()
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager);
@Bean
public TokenStore tokenStore()
return new JwtTokenStore(accessTokenConverter());
@Bean
public JwtAccessTokenConverter accessTokenConverter()
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter()
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication)
if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password"))
final Map<String, Object> additionalInfo = new HashMap<String, Object>();
additionalInfo.put("organization", authentication.getName() + randomAlphabetic(4));
((DefaultOAuth2AccessToken) accessToken)
.setAdditionalInformation(additionalInfo);
accessToken = super.enhance(accessToken, authentication);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(new HashMap<>());
return accessToken;
;
// converter.setSigningKey("123");
final KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("mytest.jks"), "mypass".toCharArray());
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
return converter;
// @Bean
// public TokenEnhancer tokenEnhancer()
// return new CustomTokenEnhancer();
//
原代码在下面
https://github.com/Baeldung/spring-security-oauth
虽然不包括我的更改,但上面的代码就足够了
测试
如您所见,body 不包含其他属性
如您所见,访问令牌具有其他属性。此外,您对 grant_type
和 password
的要求也通过
if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password"))
【讨论】:
以上是关于如何在 access_token JWT 中添加更多数据的主要内容,如果未能解决你的问题,请参考以下文章
NESTJS 网关/Websocket - 如何通过 socket.emit 发送 jwt access_token
jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?
TokenEnhancer 不仅将附加信息添加到 jwt,还添加到响应对象中
如何在 NextJS s-s-r 中存储和获取 access_token