Могу ли я включать информацию пользователя при выдаче токена доступа?
Я видел в некоторых реализациях oauth2 дополнительную информацию об ответе, возвращаемом сервером авторизации, когда он выдает токены доступа. Мне интересно, есть ли способ сделать это, используя spring -security-oauth2. Я хотел бы включить некоторые пользовательские полномочия в ответ на токен доступа, чтобы моим потребляющим приложениям не нужно было управлять полномочиями пользователей, но все равно можно настроить пользователя на свои собственные контексты безопасности и применить любые свои собственные spring - проверки безопасности.
- Как мне получить эту информацию об ответе маркера доступа?
- Как перехватить эту информацию на стороне клиента oauth2 и установить ее в контексте безопасности?
Я полагаю, что другой вариант - использовать токены JWT и делиться соответствующей информацией с клиентскими приложениями, чтобы они могли разобрать пользователь/полномочия из токена и установить его в контексте. Это делает меня более неудобным, так как я предпочел бы контролировать, какие клиентские приложения могут иметь доступ к этой информации (только доверенные приложения), и AFAIK только сервер авторизации и сервер ресурсов должны знать, как разбирать токены JWT.
Ответы
Ответ 1
Вам нужно будет реализовать пользовательский 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;
}
}
и добавьте его в свой AuthorizationServerConfigurerAdapter как bean с соответствующими сеттерами
@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, поэтому мои "некоторые автоувеличиваемые материалы здесь" соответствуют некоторым @Autowired Datasource, PasswordEncoder и что нет.
Надеюсь, это помогло!
Ответ 2
Если вы используете 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();
}
Другим решением является создание пользовательского 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();
}
Ответ 3
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;
}
}
Ответ 4
Вместе с:
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
Вы должны включить
@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
и добавьте все в конфигурацию конечных точек:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.tokenEnhancer(tokenEnhancer())
.accessTokenConverter(accessTokenConverter())
.authorizationCodeServices(codeServices)
.authenticationManager(authenticationManager)
;
}
Без этого ваш CustomTokenEnhancer не будет работать.
Ответ 5
- создать файл класса 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);
}
}
- вставьте ниже написанный код в 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);
}
- импортировать соответствующие библиотеки после вставки вышеуказанных кодов
выходной ответ Custom Token Enhancer.. нажмите здесь
Ответ 6
Я решаю эту проблему, когда исключен UserDetailsServiceAutoConfiguration. Как это. Может быть, будет полезен на серверах ресурсов OAuth2.
@SpringBootApplication(exclude = [UserDetailsServiceAutoConfiguration::class])
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}