简体   繁体   English

在Spring Security中实现自定义身份验证

[英]Implementing Custom Authentication in Spring Security

I would like to ask for your help regarding my problem in Spring Security. 我想就Spring Security中的问题向您寻求帮助。 I have a requirement wherein I have to validate a login credential based on the option selected by the user. 我有一个要求,我必须根据用户选择的选项验证登录凭据。 Option 1 would be validating the logged in user via third party service. 选项1将通过第三方服务验证登录用户。 Option 2 would be the normal validation using database authentication level. 选项2是使用数据库身份验证级别的正常验证。 How can I implement this? 我该如何实现呢?

General Strategy 一般战略

  1. Provide a custom implementation of org.springframework.security.authentication.AuthenticationProvider that delegates authentication to the appropriate backend (third-party service, another AuthenticationProvider , etc.). 提供org.springframework.security.authentication.AuthenticationProvider的自定义实现,该org.springframework.security.authentication.AuthenticationProvider将身份验证委派给适当的后端(第三方服务,另一个AuthenticationProvider等)。
  2. Pass the user-selected option to the custom AuthenticationProvider , enabling it to choose the correct authentication backend. 将用户选择的选项传递给自定义AuthenticationProvider ,使其能够选择正确的身份验证后端。
  3. Configure the custom AuthenticationProvider as the default authentication provider. 将自定义AuthenticationProvider配置为默认身份验证提供程序。

Step 1: Implement AuthenticationProvider 第1步:实现AuthenticationProvider

AuthenticationProvider is an interface with a single method. AuthenticationProvider是具有单个方法的接口。 Therefore, a custom implementation may look like: 因此,自定义实现可能如下所示:

class DelegatingAuthenticationProvider implements AuthenticationProvider {
  @Autowired
  private ThirdPartyAuthenticationService service;

  @Autowired
  @Qualifier("anotherAuthenticationProvider")
  private AuthenticationProvider provider;

  @Override
  public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
    // Get the user selection.
    String selection = (String) authentication.getDetails();

    // Take action depending on the selection.
    Authentication result;
    if("ThirdParty".equals(selection)) {
      // Authenticate using "service" and generate a new
      // Authentication "result" appropriately.
    }
    else {
      // Authenticate using "provider" and generate a new
      // Authentication "result" appropriately.
    }

    return result;
  }
}

Step 2: Pass the user selection to the AuthenticationProvider 第2步:将用户选择传递给AuthenticationProvider

The AuthenticationProvider implementation above picks up the user selection from the details property of the Authentication object. 上面的AuthenticationProvider实现从Authentication对象的details属性中选择用户选择。 Presumably, the user selection would have to be picked up from the HttpServletRequest and added to the Authentication object before the AuthenticationProvider is invoked. 据推测,所述用户选择将必须从拾取HttpServletRequest并添加到Authentication的前对象AuthenticationProvider被调用。 This means, another component that has access to both the Authentication and HttpServletRequest objects needs to be invoked before the AuthenticationProvider is called. 这意味着,在调用AuthenticationProvider之前,需要调用另一个可以访问AuthenticationHttpServletRequest对象的组件。

The Authentication object is created by an implementation of AbstractAuthenticationProcessingFilter . Authentication对象由AbstractAuthenticationProcessingFilter的实现创建。 This class has a method named attemptAuthentication that accepts an HttpServletRequest object and returns an Authentication object. 此类有一个名为attemptAuthentication的方法,该方法接受HttpServletRequest对象并返回Authentication对象。 So it seems this would be a good candidate for implementing what is needed. 因此,这似乎是实施所需内容的良好候选者。 For username-password based authentication, the implementation class is UsernamePasswordAuthenticationFilter . 对于基于用户名密码的身份验证,实现类是UsernamePasswordAuthenticationFilter This class returns a new instance of UsernamePasswordAuthenticationToken , which is an implementation of Authentication . 此类返回UsernamePasswordAuthenticationToken的新实例,该实例是Authentication的实现。 So, a class extending UsernamePasswordAuthenticationFilter should be sufficient. 因此,扩展UsernamePasswordAuthenticationFilter的类应该足够了。

class ExtendedUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    ...
    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
    authentication.setDetails(obtainUserSelection(request));

    ...

    return authentication;
  }
}

obtainUserSelection is a private method that gets the user selection out of the request. obtainUserSelection是一个私有方法,可以从请求中获取用户选择。

Step 3: Configuration 第3步:配置

Configure the AuthenticationProvider and filter implementations in the Spring Security configuration. 在Spring Security配置中配置AuthenticationProvider和过滤器实现。 The exact steps will vary depending on whether XML or Java configuration is used. 具体步骤将根据是使用XML还是Java配置而有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM