5

AuthenticationProviderカスタム セキュリティ チェックを実行するためのカスタムを作成しました。AccountStatusExceptionまた、ユーザーが特定の期間自分のアカウントを確認していない場合など、ユーザー ステータスの問題を通知するために継承するカスタム例外も作成しました。MyUserDetailsもカスタム実装です。

これは、私が実行するセキュリティ チェックのコードです。ケースに関係のないコードは省略されています。

public class SsoAuthenticationProvider implements AuthenticationProvider {

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = (String) authentication.getPrincipal();
        User user = null;
        if (username != null) {
            user = getUserRepository().findByUserName(username);
            if (user != null) {
                if (user.getEnabled() != 0) {
                    if ((user.getUserDetail().getConfirmed() != 0)
                            || ((new Date().getTime() - user.getUserDetail().getRequestDate().getTime()) / (1000 * 60 * 60 * 24)) <= getUnconfirmedDays()) {
                        if (getPasswordEncoder().isPasswordValid(user.getPassword(),
                                (String) authentication.getCredentials(), user)) {
                            user.authenticated = true;
                            user.getAuthorities();
                        }
                    } else {
                        throw new UserNotConfirmedAndTimeExceeded(
                                "User has not been cofirmed in the established time period");
                    }
                } else {
                    throw new DisabledException("User is disabled");
                }
            } else {
                throw new BadCredentialsException("User or password incorrect");
            }
        } else {
            throw new AuthenticationCredentialsNotFoundException("No credentials found in context");
        }
        return user;
    }
}

SsoAuthenticationProviderチェック:

  1. ユーザー名が登録されている(データベースに存在する)こと
  2. ユーザーがメールを確認したこと
  3. ユーザーが電子メールを確認していない場合は、まだ猶予期間内であることを確認してください (これは、サイトへのアクセスを許可しながら電子メールを確認するためにユーザーに与える数日間です)
  4. ユーザーがメールを確認しておらず、猶予期間中ではない場合、セキュリティ例外をスローしてこれらのステータスを通知し、認証を拒否します

問題は、これらの例外のすべてがコントローラーまでスタックにスローされるわけではないため、ログインの問題についてユーザーに通知することが不可能に見えることです。

UserDetailsなどの (および類似の) メソッドを使用するisEnabled()ことはできません。さまざまなユーザー アカウント ステータスのセマンティクスが完全に異なるためです。

これは、カスタム例外を使用してカスタム セキュリティを構築するための正しいアプローチですか? これを機能させるには sth else を実装する必要がありますか?

4

2 に答える 2

6

以前の質問を締めくくるために、私たちが何をしたかを説明させてください。以前の回答にコメントしたように、 UserDetails オブジェクトで提供されたメソッドを使用することは、特定のメソッドではすべてのログイン失敗セマンティクスをキャプチャできないため、現実的ではありません。私たちの場合、これらのセマンティクスはまだ非常に限られていますが、他のケースでは、さまざまなユーザーの状況を表現するために時間の経過とともに無限に拡張される可能性があります. 最終的には、例外アプローチが最適でした。最終的なコードは次のようになります

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username=(String)authentication.getPrincipal();
    User user=null;
    if(username!=null){
        user=getUserRepository().findByUserName(username);
        if(user!=null){
            if(user.getEnabled()!=0){
                if((user.getUserDetail().getConfirmed()!=0)||((new Date().getTime()-user.getUserDetail().getRequestDate().getTime())/(1000 * 60 * 60 * 24))<=getUnconfirmedDays()){
                    if(getPasswordEncoder().isPasswordValid(user.getPassword(), (String)authentication.getCredentials(), user)){
                        user.authenticated=true;
                        user.getAuthorities();
                    } else {
                        throw new BadCredentialsException("Password incorrect");
                    }
                }else{
                    throw new UserNotConfirmedAndTimeExceeded("User has not been cofirmed in the established time period");         
                }
            }else{
                throw new DisabledException("User is disabled");
            }
        }else{
            throw new BadCredentialsException("User does not exist");
        }
    }else{
        throw new AuthenticationCredentialsNotFoundException("No credentials found in context");
    }
    return user;
}

すべての例外は、春のセキュリティ例外スタックの一部です。つまり、これらのカスタム例外は既存の例外から継承されます。次に、セキュリティ コントローラでセキュリティ例外をチェックし、必要に応じて処理する必要があります。たとえば、別のページにリダイレクトします。

お役に立てれば!

于 2012-09-18T15:58:04.993 に答える
2

この目的には、ユーザー詳細オブジェクトの他のメソッド/プロパティを使用する方がよいと思います。お気に入り

isAccountNonExpired() 
isAccountNonLocked() 
isEnabled() 

カスタム エラー メッセージを表示する場合は、この記事で説明されているようにメッセージ プロパティを使用します。

于 2012-08-22T08:39:27.307 に答える