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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:21:37  来源:igfitidea点击:

can I include user information while issuing an access token?

springspring-securityspring-security-oauth2

提问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检查。

  1. How would I get that information on the access token response?
  2. How would I intercept that information on the oauth2 client side and set it on the security context?
  1. 我如何获得有关访问令牌响应的信息?
  2. 我将如何在 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 JwtAccessTokenConverteror DefaultAccessTokenConverteryou 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 JwtAccessTokenConverterand 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

  1. create a class file CustomTokenEnhancer
  1. 创建类文件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);
    }
}
  1. paste below written code in AuthorizationServerConfig
  1. 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);
}
  1. import appropriate libraries after paste the above codes
  1. 粘贴上述代码后导入适当的库

output response of Custom Token Enhancer..click here

自定义令牌增强器的输出响应..单击此处

回答by Linolium

I solve this problem when excluded UserDetailsServiceAutoConfiguration. Like this. Maybe wiil be helpful in OAuth2 resource servers.

我在排除 UserDetailsS​​erviceAutoConfiguration 时解决了这个问题。像这样。也许会在 OAuth2 资源服务器中有所帮助。

@SpringBootApplication(exclude = [UserDetailsServiceAutoConfiguration::class])
class Application

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}