Spring Security Oauth2 使用自定义身份验证登录

问题描述 投票:0回答:2

我正在使用 Spring Boot 3 和 Spring Security 6。

我的目标是实现使用 JWT 令牌的登录功能。登录页面应该有两个选项:

  • 自定义登录/注册表单
  • 使用Google登录(OAuth2登录)

自定义身份验证流程的工作原理如下:

  • 用户通过登录页面输入用户名和密码。
  • 从数据库中获取用户名,并检查密码是否匹配。
  • 然后生成 JWT 令牌并在响应中返回。
  • 客户端应用程序使用此 JWT 令牌进行后续请求。

我想使用Google flow登录应该包括以下步骤:

当我在用户授予访问权限后收到来自 Google 重定向的授权代码时,我将继续执行以下步骤。

  • 将授权代码交换为访问令牌并进行验证。
  • 从 Google 获取用户信息。
  • 从数据库创建或获取用户。
  • 生成与自定义身份验证流程中相同类型的 JWT 令牌。
  • 将 JWT 令牌添加到响应中并将其重定向到我的 UI 应用程序。
  • UI 应用程序然后使用提供的 JWT 令牌处理后续请求。

分析 Spring Security 的默认功能后,我发现

OAuth2LoginAuthenticationFilter
负责在授权服务器使用代码重定向后进行身份验证。

看来这个过滤器大致执行以下步骤:

  • 从会话中获取原始身份验证请求。
  • 执行代码/令牌交换。
  • 验证令牌。
  • 从 Google 获取用户信息。
  • 验证用户身份。

因此,我知道我需要创建此过滤器的自定义版本并实施我为我的用例设计的步骤。

但是,我发现 Spring Security 不允许为 OAuth2 登录设置自定义过滤器。它与

OAuth2LoginAuthenticationFilter
紧密结合。请查看此处的 OAuth2LoginConfigurer 类定义。

public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> extends AbstractAuthenticationFilterConfigurer<B, OAuth2LoginConfigurer<B>, OAuth2LoginAuthenticationFilter> {

您对如何正确实现此功能有什么想法吗?

如果我的流程对您来说不合适,我也愿意接受替代解决方案。

spring spring-boot authentication jwt spring-oauth2
2个回答
0
投票

在 OAuth2 中,登录(授权代码流)由客户端发起,并重定向到授权服务器。

登录步骤(用户名/密码形式、MFA、使用Google登录等)是授权服务器业务。您在 Spring Security OAuth2 客户端 API 中探索的内容是在用户在授权服务器上进行身份验证后调用的。

因此,您请求的是一个“使用 Google 登录”的授权服务器。您可以使用 Spring 授权服务器项目编写自己的项目,“从货架上”选择一个(例如 Keycloak)或在众多云产品(Auth0、Amazon Cognito、Azure AD 等)中进行选择。几乎都有社交登录功能。


0
投票

我一直在一个 Spring boot 应用程序中工作,我尝试允许我的用户/客户使用其凭据或使用 google OAuth2 登录,然后向他们返回 JWT 令牌。 所以基本上我所做的就是创建一个从 SimpleUrlAuthenticationSuccessHandler 扩展的类,在其中我在成功的 OAuth2 身份验证后自定义行为,在该类中我获取身份验证的信息(它是 OAuth2User),并且如果它包含的电子邮件存在于其中,我就有效我的数据库,如果属实,我将继续创建令牌的过程。 看代码:

@Configuration
public class CustomOAuth2AuthenticationSuccessHandler extends 
SimpleUrlAuthenticationSuccessHandler {
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    private JwtService jwtService;
    @Autowired
    private TokenRepository tokenRepository;
    @Override
    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication) throws IOException, 
    ServletException {

        if(authentication instanceof OAuth2AuthenticationToken){
           OAuth2User oauth2User = ((OAuth2AuthenticationToken) 
authentication).getPrincipal();
            Customer customer = customerRepository.
                         findCustomerByEmail(oauth2User.getAttribute("email").toString()).
orElse(null);
            if(customer!=null){
                System.out.println("customer exist");
                String token = jwtService.generateToken(customer);
                //more process you have to do in your logic
                response.getWriter().write(token);
                response.getWriter().flush();

            }else{
                //customer doesn't exist, throw an error or create new one
            }
        }else{
            //error
        }

       }
}

在我的配置类中,我添加了 CustomOAuth2AuthenticationSuccessHandler 类。

    .oauth2Login(oauth->{         
oauth.successHandler(customOAuth2AuthenticationSuccessHandler);
                    oauth.failureHandler(new 
SimpleUrlAuthenticationFailureHandler("/login?error=true"));
                           })

这就是我允许用户使用其凭据或使用 OAuth2 google 进行登录的方式。我正在使用 Spring boot 3 和 Spring security 6。也许这可以帮助你:)

© www.soinside.com 2019 - 2024. All rights reserved.