spring 我可以在颁发访问令牌时包含用户信息吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28492116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
can I include user information while issuing an access token?
提问by RutledgePaulV
I have seen in some oauth2 implementations additional information on the response returned by the authorization server when it issues access tokens. I'm wondering if there is a way to accomplish this using spring-security-oauth2. I would love to be able to include some user authorities on the access token response so that my consuming applications don't need to manage the user authorities but can still set the user on their own security contexts and apply any of their own spring-security checks.
我在一些 oauth2 实现中看到了有关授权服务器在发出访问令牌时返回的响应的附加信息。我想知道是否有办法使用 spring-security-oauth2 来实现这一点。我希望能够在访问令牌响应中包含一些用户权限,以便我的消费应用程序不需要管理用户权限,但仍然可以在他们自己的安全上下文中设置用户并应用他们自己的任何 spring-security检查。
- How would I get that information on the access token response?
- How would I intercept that information on the oauth2 client side and set it on the security context?
- 我如何获得有关访问令牌响应的信息?
- 我将如何在 oauth2 客户端拦截该信息并将其设置在安全上下文中?
I suppose another option would be to use JWT tokens and share the appropriate information with the client applications so that they can parse the user / authorities out of the token and set it on the context. This makes me more uncomfortable since I'd prefer to be in control of which client applications could have access to this information (trusted apps only) and AFAIK only the authorization server and resource server should know how to parse the JWT tokens.
我想另一种选择是使用 JWT 令牌并与客户端应用程序共享适当的信息,以便他们可以从令牌中解析用户/权限并将其设置在上下文中。这让我更不舒服,因为我更愿意控制哪些客户端应用程序可以访问这些信息(仅限受信任的应用程序),而 AFAIK 只有授权服务器和资源服务器应该知道如何解析 JWT 令牌。
回答by Philippe
You will need to implement a custom TokenEnhancer like so:
您需要像这样实现自定义 TokenEnhancer:
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
User user = (User) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("customInfo", "some_stuff_here");
additionalInfo.put("authorities", user.getAuthorities());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
and add it to your AuthorizationServerConfigurerAdapter as a bean with the corresponding setters
并将其作为具有相应设置器的 bean 添加到您的 AuthorizationServerConfigurerAdapter
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
// Some autowired stuff here
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// @formatter:off
endpoints
// ...
.tokenEnhancer(tokenEnhancer());
// @formatter:on
}
@Bean
@Primary
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
// ...
tokenServices.setTokenEnhancer(tokenEnhancer());
return tokenServices;
}
// Some @Bean here like tokenStore
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
then in a controller (for example)
然后在控制器中(例如)
@RestController
public class MyController {
@Autowired
private AuthorizationServerTokenServices tokenServices;
@RequestMapping(value = "/getSomething", method = RequestMethod.GET)
public String getSection(OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = tokenServices.getAccessToken(authentication).getAdditionalInformation();
String customInfo = (String) additionalInfo.get("customInfo");
Collection<? extends GrantedAuthority> authorities = (Collection<? extends GrantedAuthority>) additionalInfo.get("authorities");
// Play with authorities
return customInfo;
}
}
I'm personnaly using a JDBC TokenStore so my "Some autowired stuff here" are corresponding to some @Autowired Datasource, PasswordEncoder and what not.
我个人正在使用 JDBC TokenStore,所以我的“这里的一些自动装配的东西”对应于一些 @Autowired 数据源、PasswordEncoder 等等。
Hope this helped!
希望这有帮助!
回答by jchrbrt
If you are using Spring's JwtAccessTokenConverter
or DefaultAccessTokenConverter
you can add your custom CustomTokenEnhancer(see first response) and apply it using a TokenEnhancerChainlike this:
如果您使用的是 Spring,JwtAccessTokenConverter
或者DefaultAccessTokenConverter
您可以添加您的自定义CustomTokenEnhancer(请参阅第一个响应)并使用TokenEnhancerChain应用它,如下所示:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(enhancerChain)
.authenticationManager(authenticationManager);
}
@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("my_signing_key");
return converter;
}
@Bean public TokenEnhancer customTokenEnhancer() {
return new CustomTokenEnhancer();
}
Another solution is to create a custom TokenConverter that extends Spring's JwtAccessTokenConverter
and override the enhance()method with your custom claims.
另一种解决方案是创建一个自定义 TokenConverter 来扩展 SpringJwtAccessTokenConverter
并使用您的自定义声明覆盖Enhance ()方法。
public class CustomTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
final Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("customized", "true");
User user = (User) authentication.getPrincipal();
additionalInfo.put("isAdmin", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()).contains("BASF_ADMIN"));
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return super.enhance(accessToken, authentication);
}
}
And then:
进而:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore())
.tokenEnhancer(customTokenEnhancer())
.authenticationManager(authenticationManager);
}
@Bean public CustomTokenConverter customTokenEnhancer() {
return new CustomTokenConverter();
}
回答by harshlal028
package com.security;
import java.util.HashMap;
import java.util.Map;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;
@Component
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
// TODO Auto-generated method stub
User user = (User) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("customInfo", "some_stuff_here");
additionalInfo.put("authorities", user.getAuthorities());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
Following is the xml configuration:
以下是xml配置:
<bean id="tokenEnhancer" class="com.security.CustomTokenEnhancer" />
<!-- Used to create token and and every thing about them except for their persistence that is reposibility of TokenStore (Given here is a default implementation) -->
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="accessTokenValiditySeconds" value="30000000"></property>
<property name="refreshTokenValiditySeconds" value="300000000"></property>
<property name="supportRefreshToken" value="true"></property>
<property name="clientDetailsService" ref="clientDetails"></property>
<property name="tokenEnhancer" ref="tokenEnhancer" />
</bean>
That's how I was able to add extra information to the Token.
这就是我能够向令牌添加额外信息的方式。
回答by Yaroslav
Together with:
和...一起:
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
You have to include
你必须包括
@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
and add everything to endpoints config:
并将所有内容添加到端点配置:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.tokenEnhancer(tokenEnhancer())
.accessTokenConverter(accessTokenConverter())
.authorizationCodeServices(codeServices)
.authenticationManager(authenticationManager)
;
}
Without it, your CustomTokenEnhancerwill not work.
没有它,您的CustomTokenEnhancer将无法工作。
回答by Anjali K A
- create a class file CustomTokenEnhancer
- 创建类文件CustomTokenEnhancer
@Component
public class CustomTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
final Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("customized", "true");
User user = (User) authentication.getPrincipal();
additionalInfo.put("role", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return super.enhance(accessToken, authentication);
}
}
- paste below written code in AuthorizationServerConfig
- 在AuthorizationServerConfig 中粘贴以下编写的代码
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(),accessTokenConverter()));
endpoints
.tokenStore(tokenStore())
.tokenEnhancer(customTokenEnhancer())
.authenticationManager(authenticationManager);
}
@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
JwtAccessTokenConverter converter= new JwtAccessTokenConverter();
converter.setSigningKey("my_signing_key");
return converter;
}
@Bean
public CustomTokenConverter customTokenEnhancer() {
return new CustomTokenConverter();
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
- import appropriate libraries after paste the above codes
- 粘贴上述代码后导入适当的库
回答by Linolium
I solve this problem when excluded UserDetailsServiceAutoConfiguration. Like this. Maybe wiil be helpful in OAuth2 resource servers.
我在排除 UserDetailsServiceAutoConfiguration 时解决了这个问题。像这样。也许会在 OAuth2 资源服务器中有所帮助。
@SpringBootApplication(exclude = [UserDetailsServiceAutoConfiguration::class])
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}