【问题标题】:Handle OAuth2 callback in Spring Boot在 Spring Boot 中处理 OAuth2 回调
【发布时间】:2020-04-23 15:38:08
【问题描述】:

我正在尝试构建一个需要登录到 OAuth2 SSO 的 Spring Boot 项目。 我有以下 Maven 依赖项:

org.springframework.boot:spring-boot-starter-web
org.springframework.security:spring-security-oauth2-client
org.springframework.security:spring-security-config

我使用HttpSecurity 为应用强制执行 OAuth2 身份验证,使用以下内容:

@EnableWebSecurity
@Order(101)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatcher("/api/auth/oauth2/callback").permitAll()
            .anyRequest().authenticated()
            .and()
            .oauth2Login();
    }

}

现在,它的作用是:它看到用户未登录,将他们重定向到 SSO,并在他们登录后将用户重定向回 /api/auth/oauth2/callback?code=...&state=... 端点。这一切都很好。但是,我对 Spring Boot 还很陌生,我不明白我如何坚持用户现在已通过身份验证的事实(我知道我仍然需要验证回调,这不是问题)。

这是我想要实现的身份验证模型:我想在回调端点内生成一个哈希,并将该哈希存储在应用程序的内存中,并作为用户浏览器上的 cookie。然后,在任何后续请求中,应用程序将读取该 cookie 的值,在内存数据库中找到包含哈希的行,并从数据库行中获取相应的用户数据。

我已经广泛地查看了一个很好的例子,但是,所有基于 Spring Boot 的 OAuth2 示例都使用 Github/Google OAuth,而且它似乎可以在后台处理很多东西(或也许我没有正确理解这些)。

任何帮助/指导将不胜感激!

如果有帮助,这是我的application.yml 文件:

spring:
  security:
    oauth2:
      client:
        registration:
          custom_sso_name:
            clientId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
            clientSecret: SUPER_SECRET
            authorizationGrantType: authorization_code
            redirectUri: https://dev.localhost/api/auth/oauth2/callback
        provider:
          custom_sso_name:
            userInfoUri: https://sso.example.com/nidp/oauth/nam/userinfo
            authorizationUri: https://sso.example.com/nidp/oauth/nam/authz
            tokenUri: https://sso.example.com/nidp/oauth/nam/token
            preferTokenInfo: false

【问题讨论】:

  • 嗨,你找到什么了吗?我遇到了完全相同的问题...
  • @CarlosLópezMarí 我确实通过使用 SpringSecurityContext 找到了解决方案,当我找到时间时,我会在此处发布我的解决方案,同时,请参阅此页面,它帮助我了解如何设置登录用户:baeldung.com/manually-set-user-authentication-spring-security
  • 天啊,我正在寻找有关如何手动登录用户的任何文章,但没有找到任何东西。也许“手动”这个词毕竟是关键......谢谢!
  • 好吧,这并没有给我访问令牌或任何东西,所以我想我要使用 REST 客户端和 Cookie...
  • 在我的情况下,我编写了接收 oauth2 回调并自己获取访问令牌的端点——我唯一想要的就是能够在完成后登录用户。

标签: java spring spring-boot oauth-2.0


【解决方案1】:

您可以查看Authentication Provider

设置后,您可以自动装配自定义 AuthenticationProvider 并使用 SecurityContext 在您的控制器中登录用户,如下所示:

    SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(new UserInfo(yourHash, token, expirationDate)));

这里,UserInfo 是一个示例类(扩展 AbstractAuthenticationToken),它可以保存您想要保存的哈希值,以及您可能需要的任何其他数据。

在上述链接的示例中,他们使用UsernamePasswordAuthenticationToken,如果您只想存储哈希值,这对您来说可能已经足够了。如果您想存储额外信息,我建议您使用自定义 AuthenticationToken,因为它是 UserInfo:

public class UserInfo extends AbstractAuthenticationToken {


    private String hash;
    private String oAuthToken;
    private DateTime expirationTime;

    public UserInfo (String hash, String oAuthToken, DateTime expirationTime){
        super(Collections.emptyList());
        this.hash= hash;
        this.oAuthToken = oAuthToken;
        this.expirationTime = expirationTime;
    }

    @Override
    public String getCredentials() {
       if(expirationTime.isAfter(DateTime.now())){
           return oAuthToken;
       } else {
           return null;
       }
    }

    @Override
    public String getPrincipal() {
        return hash;  //Or anything you stored that may be useful for checking the authentication
    }

然后,在任何后续请求中,应用程序都会读取该 cookie 的 值,在内存数据库中找到包含哈希的行,然后 从数据库行中获取对应的用户数据。

本次鉴权完成后,可以在任意请求中自定义检查鉴权:

@GetMapping("/")
public String profileSettings(Principal principal) {

    if (principal instanceof UserInfo){
        String hash = ((UserInfo) principal).getPrincipal();
       //Now you can use the hash for your custom logic, such like database reading
       return "profileSettings";
    } else {
       return "login";
    }
}

【讨论】:

    猜你喜欢
    • 2016-06-29
    • 1970-01-01
    • 2017-02-12
    • 2016-10-28
    • 2017-09-11
    • 2018-08-13
    • 2020-10-25
    • 1970-01-01
    • 2022-11-03
    相关资源
    最近更新 更多