У меня есть AuthorizationServer. Помимо стандартных функций у меня есть контроллер, который позволяет создавать пользователя. После успешного создания пользователем метод должен вернуть токен для этого пользователя. Проблема в том, что метод возвращает действительный токен только при первом вызове. При следующих звонках - следующие пользователи получат токен первого пользователя. Я попытался установить область (запрос) для restTemplate - но получил ошибку: «Область 'запрос' не активна для текущего потока»

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {  

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
      ...
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
     ...
    }

    protected ResourceOwnerPasswordResourceDetails getOwnerPasswordResource(){
        ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
        List scopes = new ArrayList<String>(3);
        scopes.add(SCOPE_READ);
        scopes.add(SCOPE_WRITE);
        scopes.add(SCOPE_TRUST);
        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId(CLIENT_ID);
        resource.setClientSecret(CLIENT_SECRET_UNCODED);
        resource.setGrantType(GRANT_TYPE_PASSWORD);
        resource.setScope(scopes);
        return resource;
    }
}

Вот OAuth2Client:

@EnableOAuth2Client
@Configuration
public class ClientConfig {
    @Autowired
    AuthorizationServerConfig authorizationServerConfig;

    @Bean
    //@Scope("request")
    public OAuth2RestOperations restTemplate() {
        AccessTokenRequest atr = new DefaultAccessTokenRequest();

        return new OAuth2RestTemplate(authorizationServerConfig.getOwnerPasswordResource(), new DefaultOAuth2ClientContext(atr));
    }

}

И мой контроллер:

@RestController
public class UserRestController {
    @Autowired
    private OAuth2RestOperations restTemplate;

    @PostMapping("/user")
    public OAuth2AccessToken createUserCredential(@RequestBody UserCredential user) {
        user.validate();
        userCredentialService.checkAndSaveUser(user, getClientIp(request));

        restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("username", user.getLogin());
        restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("password", user.getPassword);
        return restTemplate.getAccessToken();
    }
}

Может есть более правильный способ получить токен внутри AuthorizationServer?

0
T_E_M_A 22 Июн 2018 в 09:48

2 ответа

Лучший ответ

Думал есть какой-то особенный способ .. но не нашел. И решил проблему следующим образом

 @EnableOAuth2Client
@Configuration
public class OAuthClientConfig {

    @Autowired
    AuthorizationServerConfig authorizationServerConfig;

    public OAuth2RestOperations restTemplate() {
        AccessTokenRequest atr = new DefaultAccessTokenRequest();

        return new OAuth2RestTemplate(authorizationServerConfig.getOwnerPasswordResource(), new DefaultOAuth2ClientContext(atr));
    }
}

И мой контроллер:

@RestController
public class UserRestController {

    @Autowired
    private OAuthClientConfig oAuthClientConfig;

    @PostMapping("/user")
    public OAuth2AccessToken createUserCredential(@RequestBody UserCredential user) {
        user.validate();
        userCredentialService.checkAndSaveUser(user, getClientIp(request));

        OAuth2RestOperations restTemplate = oAuthClientConfig.restTemplate();
        restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("username", user.getLogin());
        restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("password", user.getPassword);
        return restTemplate.getAccessToken();
    }
}

Может кому поможет

0
T_E_M_A 22 Июн 2018 в 11:47

Я столкнулся с той же проблемой, что нашел другой способ заставить ее работать

@Bean
@Primary
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext context,
            OAuth2ProtectedResourceDetails details) {

        AccessTokenRequest atr = new DefaultAccessTokenRequest();
        OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
        AccessTokenProvider accessTokenProvider = new AccessTokenProviderChain(Arrays.<AccessTokenProvider>asList(
                new AuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(),
                new ResourceOwnerPasswordAccessTokenProvider(), new ClientCredentialsAccessTokenProvider()));
        template.setAccessTokenProvider(accessTokenProvider);
        return template;

    }

А потом я просто сделал укол

private final OAuth2RestTemplate oauth2RestTemplate;
    @GetMapping(path = "/token")
    public String token(Credentials  credentials) {
    oauth2RestTemplate.getOAuth2ClientContext()
             .getAccessTokenRequest().add("username", credentials.getEmail());
    oauth2RestTemplate.getOAuth2ClientContext()
             .getAccessTokenRequest().add("password", credentials.getPass());
    final OAuth2AccessToken accessToken = oauth2RestTemplate.getAccessToken();
    final String accessTokenAsString = accessToken.getValue();
    return accessTokenAsString ;
    }
0
Rodrigo Bautista 8 Июн 2020 в 11:14