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);
}
}
我使用 @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);
}
}