Spring Rest OAuth2 AuthorizationServer:在 n 次登录尝试失败后停用用户

Spring Rest OAuth2 AuthorizationServer: Deactivate user after n failed login attempts

我使用 @EnableAuthorizationServer 为我的 REST API 获取 OAuth2 AuthorizationServer。有用。现在我想在 10 次登录尝试失败后禁用用户帐户。

我尝试配置自定义 AuthenticationManager,但没有被调用。

这是我的 AuthorizationServerConfigurerAdapter:

@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class OAuth2AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

  @Autowired
  private AuthenticationClientDetailsService clientDetailsService;

  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();
  }

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.withClientDetails(clientDetailsService());
  }

  private ClientDetailsService clientDetailsService() {
    return clientDetailsService;
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.tokenStore(tokenStore()).tokenEnhancer(tokenEnhancer()).authenticationManager(authenticationManager());
  }

  @Bean
  public TokenStore tokenStore() {
    return new InMemoryTokenStore();
  }

  @Bean
  public TokenEnhancer tokenEnhancer() {
    return new CustomTokenEnhancer();
  }

  @Bean
  public AuthenticationManager authenticationManager() {
    return new CustomAuthenticationManager();
  }
}

这是我的假人 AuthenticationManager:

@Log4j
public class CustomAuthenticationManager implements AuthenticationManager {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.error("I woz called!");
        authentication.setAuthenticated(true);
        return authentication;
    }

}

我希望在请求令牌时调用 CustomAuthenticationManager.authenticate(),这样我就可以检查凭据并相应地锁定帐户,但是永远不会调用该方法:-(

我让它工作的唯一方法是使用自定义 TokenEndpointAuthenticationFilter:

AuthenticationManagerProvider

这是必要的,因为您需要 AuthenticationManager 来实例化 TokenEndpointAuthenticationFilter,并且您希望 Spring 已自动实例化。

@Configuration // @Order(99) is important so this bean is initialized before the
@Order(99)     // AuthorizationServerConfigurer at 100           
public class AuthenticationManagerProvider extends WebSecurityConfigurerAdapter {
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

AuthorizationServerConfigurerAdapter

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    AuthenticationManager authenticationManager = authenticationManagerProvider.authenticationManagerBean();
    DefaultOAuth2RequestFactory oAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
    CustomAuthenticationFilter filter = new CustomAuthenticationFilter(authenticationManager, oAuth2RequestFactory);

    security.tokenKeyAccess("permitAll()") //
        .checkTokenAccess("isAuthenticated()") //
        .allowFormAuthenticationForClients() //
        .addTokenEndpointAuthenticationFilter(filter);
}

CustomAuthenticationFilter

您可能可以专门覆盖成功和不成功的身份验证尝试,但在我的情况下,我需要处理这两个问题以重置成功尝试的失败次数并在达到最大值时锁定帐户,所以我决定直接覆盖 doFilter()

请记住在最后调用超级实现,否则您的客户将无法获得令牌!

public class CustomAuthenticationFilter extends TokenEndpointAuthenticationFilter {

    public CustomAuthenticationFilter(AuthenticationManager authenticationManager, OAuth2RequestFactory oAuth2RequestFactory) {
        super(authenticationManager, oAuth2RequestFactory);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // do your thing, then call super-implementation to continue normal authentication flow
        super.doFilter(request, response, chain);
    }
}