Spring Security 在颁发访问令牌时,我是否可以包含用户信息?

vfhzx4xs  于 2023-08-05  发布在  Spring
关注(0)|答案(6)|浏览(107)

我在一些oauth2实现中看到了授权服务器在发出访问令牌时返回的响应的附加信息。我想知道是否有一种方法可以使用spring-security-oauth2来实现这一点。我希望能够在访问令牌响应中包含一些用户权限,这样我的消费应用程序就不需要管理用户权限,但仍然可以在自己的安全上下文中设置用户并应用任何自己的spring-security检查。
1.如何获得访问令牌响应的信息?
1.如何在oauth2客户端截获该信息并将其设置在安全上下文上?
我认为另一种选择是使用JWT令牌并与客户端应用程序共享适当的信息,以便它们可以从令牌中解析出用户/权限并将其设置在上下文中。这让我更不舒服,因为我更喜欢控制哪些客户端应用程序可以访问此信息(仅受信任的应用程序),并且AFAIK只有授权服务器和资源服务器应该知道如何解析JWT令牌。

os8fio9y

os8fio9y1#

你需要实现一个自定义的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;
    }

}

字符串
并将其作为具有相应setter的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();
    }

}


然后在控制器中(例如)

@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;
    }

}


我个人使用的是JDBC TokenStore,所以我的“Some autowired stuff here”对应的是一些@Autowired Datasource,PasswordEncoder等等。
希望这有帮助!

5cg8jx4n

5cg8jx4n2#

如果你正在使用Spring的JwtAccessTokenConverterDefaultAccessTokenConverter,你可以添加你的自定义 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();
}

字符串
另一个解决方案是创建一个自定义TokenConverter,它扩展Spring的JwtAccessTokenConverter,并使用自定义声明覆盖 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);
    }
}


然后:

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

    endpoints.tokenStore(tokenStore())
            .tokenEnhancer(customTokenEnhancer())
            .authenticationManager(authenticationManager);
}

@Bean public CustomTokenConverter customTokenEnhancer() {
    return new CustomTokenConverter();
}

rhfm7lfc

rhfm7lfc3#

连同:

@Bean
public TokenEnhancer tokenEnhancer() {
   return new CustomTokenEnhancer();
}

字符串
你必须包括

@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
    return new DefaultAccessTokenConverter();
}


并将所有内容添加到endpoints config:

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

        endpoints
                .tokenStore(tokenStore)
                .tokenEnhancer(tokenEnhancer())
                .accessTokenConverter(accessTokenConverter())
                .authorizationCodeServices(codeServices)
                .authenticationManager(authenticationManager)
        ;
    }


没有它,您的CustomTokenEnhancer将无法工作。

mbskvtky

mbskvtky4#

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;
	}

}

字符串
以下是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>


所以我才能在令牌里添加额外的信息

lmyy7pcs

lmyy7pcs5#

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.将下面编写的代码粘贴到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.粘贴上述代码后导入适当的库
output response of Custom Token Enhancer..click here

6ioyuze2

6ioyuze26#

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

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

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

字符串

相关问题