【问题标题】:Spring Security 5.2 Password FlowSpring Security 5.2 密码流程
【发布时间】:2020-04-10 12:09:34
【问题描述】:

我正在尝试使用最新版本的 Spring Security - 5.2 中的密码流对用户进行身份验证。

docs seem to suggest 怎么做。

@Bean
public OAuth2AuthorizedClientManager passwordFlowAuthorizedClientManager(
        HttpClient httpClient,
        ClientRegistrationRepository clientRegistrationRepository,
        OAuth2AuthorizedClientRepository authorizedClientRepository) {

    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);

    DefaultPasswordTokenResponseClient c = new DefaultPasswordTokenResponseClient();
    RestTemplate client = new RestTemplate(requestFactory);
    client.setMessageConverters(Arrays.asList(
            new FormHttpMessageConverter(),
            new OAuth2AccessTokenResponseHttpMessageConverter()));
    client.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
    c.setRestOperations(client);

    OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .password(configurer -> configurer.accessTokenResponseClient(c))
                .refreshToken()
                .build();

    DefaultOAuth2AuthorizedClientManager authorizedClientManager =
            new DefaultOAuth2AuthorizedClientManager(
                    clientRegistrationRepository, authorizedClientRepository);
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    authorizedClientManager.setContextAttributesMapper(authorizeRequest -> {
        Map<String, Object> contextAttributes = new HashMap<>();
        String username = authorizeRequest.getAttribute(OAuth2ParameterNames.USERNAME);
        String password = authorizeRequest.getAttribute(OAuth2ParameterNames.PASSWORD);
        contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
        contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
        return contextAttributes;
    });

    return authorizedClientManager;
}



我执行了请求,我可以看到 HTTP 标头中返回的访问令牌,但 SecurityContext 未填充,会话用户保持匿名。

String username = "joe";
String password = "joe";
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
ClientRegistration r = clientRegistrationRepository.findByRegistrationId("keycloak");

OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(r.getRegistrationId())
        .principal(authentication)
        .attributes(attrs -> {
            attrs.put(OAuth2ParameterNames.USERNAME, username);
            attrs.put(OAuth2ParameterNames.PASSWORD, password);
        })
        .build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);

有什么想法吗?

【问题讨论】:

标签: spring spring-security oauth-2.0 spring-security-oauth2


【解决方案1】:

在阅读了更多文档之后,我认为 Spring Security 5.2 中的 Oauth 2 密码流不像授权流那样受支持。 Spring Security 5.2 具有对 http 客户端的密码流支持,它可以缓存授权请求并在令牌过期之前刷新令牌 - 但没有最终用户密码流支持客户端将凭据代理到授权服务器。

当然,完全可以通过获取凭据来对最终用户进行身份验证,实现一个自定义 AuthenticationProvider,将凭据交换为与授权服务器的令牌,并返回一个持久化到上下文的 OAuth2AuthenticationToken。

【讨论】:

  • 在这个主题或任何代码示例方面有更多进展吗?对于我正在从事的项目,这正是我所需要的。我试图了解我是否应该这样做,但找不到我不应该这样做的原因。如果是这样,可能Spring项目考虑这个问题并可能在项目中实现是好的。
猜你喜欢
  • 2011-12-12
  • 2014-02-14
  • 1970-01-01
  • 2012-01-17
  • 2014-04-23
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
相关资源
最近更新 更多