web-dev-qa-db-ja.com

Spring Securityでログイン試行を制限するにはどうすればよいですか?

ログイン試行を制限するための構成または使用可能なモジュールがSpringSecurityにありますか(理想的には、後続の失敗した試行間の待機時間を増やしたい)?そうでない場合は、APIのどの部分をこれに使用する必要がありますか?

19

DB内のカウント/時間を更新するAuthenticationFailureHandlerを実装します。とにかく攻撃者がCookieを送信することはないので、セッションの使用は期待していません。

15
sourcedelica

Spring 4.2以降 アノテーションベースのイベントリスナー が利用可能です:

@Component
public class AuthenticationEventListener {

    @EventListener
    public void authenticationFailed(AuthenticationFailureBadCredentialsEvent event) {

        String username = (String) event.getAuthentication().getPrincipal();

        // update the failed login count for the user
        // ...
    }

}
13
Markus Pscheidt

http://forum.springsource.org/showthread.php?108640-Login-attempts-Spring-security でRob Winchが提案したように、私はDaoAuthenticationProviderをサブクラス化しました(これも可能です)失敗したログインの数を制限するために、Riteshが提案するアスペクトを使用して実行されていますが、前提条件をアサートすることもできます。

public class LimitingDaoAuthenticationProvider extends DaoAuthenticationProvider {
  @Autowired
  private UserService userService;
    @Override
    public Authentication authenticate(Authentication authentication)
        throws AuthenticationException {
      // Could assert pre-conditions here, e.g. rate-limiting
      // and throw a custom AuthenticationException if necessary

      try {
        return super.authenticate(authentication);
      } catch (BadCredentialsException e) {
        // Will throw a custom exception if too many failed logins have occurred
        userService.recordLoginFailure(authentication);
        throw e;
      }
   }
}

Spring config XMLで、次のBeanを参照するだけです。

<beans id="authenticationProvider"   
    class="mypackage.LimitingDaoAuthenticationProvider"
    p:userDetailsService-ref="userDetailsService"
    p:passwordEncoder-ref="passwordEncoder"/>

<security:authentication-manager>
    <security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>

AuthenticationExceptionauthenticationまたはextraInformationプロパティへのアクセスに依存するソリューション(AuthenticationFailureHandlerの実装など)は、おそらく使用すべきではないと思います。プロパティは非推奨になりました(少なくともSpring Security 3.1では)。

5
paulcm

最近、JMXを使用してログインの失敗を監視するための同様の機能を実装しました。質問に対する私の回答のコードを参照してください NotificationPublisherAwareなしでSpringを使用してJMX通知を公開する 。認証プロバイダーの認証方法の側面は、MBeanを更新し、通知リスナー(その質問には示されていないコード)と連携して、ユーザーとIPをブロックし、アラートEメールを送信し、障害がしきい値を超えた場合にログインを一時停止します。

編集
質問への私の回答と同様 春のセキュリティ3:認証に関する情報をデータベースに保存する 、認証失敗イベントをキャプチャし(ハンドラーをカスタマイズするのではなく)、データベースに情報を保存すると思いますまた、機能し、コードも分離されたままになります。

5
Ritesh

ApplicationListener <AuthenticationFailureBadCredentialsEvent>を実装するサービスを使用して、DBのレコードを更新することもできます。

春のアプリケーションイベントを参照してください。

4
Xavier Dury

これが私の実装です。助けてください。

  1. 無効なログイン試行を保存するテーブルを作成します。
  2. 無効な試行が最大許容値を超える場合は、UserDetail.accountNonLockedをfalseに設定します
  3. SpringSecurityが「ロックプロセス」を処理します。 (AbstractUserDetailsAuthenticationProviderを参照)

最後に、DaoAuthenticationProviderを拡張し、内部のロジックを統合します。

@Component("authenticationProvider")
public class YourAuthenticationProvider extends DaoAuthenticationProvider {

@Autowired
UserAttemptsDao userAttemptsDao;

@Override
public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {

  try {

    Authentication auth = super.authenticate(authentication);

    //if corrent password, reset the user_attempts
    userAttemptsDao.resetFailAttempts(authentication.getName());

    return auth;

  } catch (BadCredentialsException e) { 

    //invalid login, update user_attempts, set attempts+1 
    userAttemptsDao.updateFailAttempts(authentication.getName());

    throw e;

  } 

}


}

完全なソースコードと実装については、これを参照してください 春のセキュリティ制限ログイン試行の例

4
mkyong
  1. 失敗した試行の値を格納するテーブルを作成します例:user_attempts
  2. カスタムイベントリスナーを作成する

     @Component("authenticationEventListner")
     public class AuthenticationEventListener
     implements AuthenticationEventPublisher
     {
     @Autowired
     UserAttemptsServices userAttemptsService;
    
     @Autowired
     UserService userService;
    
     private static final int MAX_ATTEMPTS = 3;
     static final Logger logger = LoggerFactory.getLogger(AuthenticationEventListener.class);   
    
     @Override
     public void publishAuthenticationSuccess(Authentication authentication) {          
     logger.info("User has been logged in Successfully :" +authentication.getName());       
     userAttemptsService.resetFailAttempts(authentication.getName());       
     }
    
    
     @Override
     public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {               
     logger.info("User Login failed :" +authentication.getName());      
     String username = authentication.getName().toString();
     UserAttempts userAttempt =  userAttemptsService.getUserAttempts(username);
     User userExists = userService.findBySSO(username);
    
     int attempts = 0;
     String error = "";
     String lastAttempted = "";             
     if (userAttempt == null) {     
    
        if(userExists !=null ){                     
        userAttemptsService.insertFailAttempts(username);   }       
      } else {                
          attempts = userAttempt.getAttempts();
          lastAttempted = userAttempt.getLastModified();
        userAttemptsService.updateFailAttempts(username, attempts);         
        if (attempts + 1 >= MAX_ATTEMPTS) {                 
            error = "User account is locked! <br>Username : "
                           + username+ "<br>Last Attempted on : " + lastAttempted;          
        throw new LockedException(error);           
        }                                   
      }
    throw new BadCredentialsException("Invalid User Name and Password");
    
    
    
     }
      }
    

3.セキュリティ構成

         1) @Autowired
         @Qualifier("authenticationEventListner")
         AuthenticationEventListener authenticationEventListner;

      2) @Bean
         public AuthenticationEventPublisher authenticationListener() {
         return new AuthenticationEventListener();
         }
      3) @Autowired
         public void 
         configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
         //configuring custom user details service
         auth.authenticationProvider(authenticationProvider);
         // configuring login success and failure event listener
         auth.authenticationEventPublisher(authenticationEventListner);
         }
1
Vimal Ananda