3

最初のログイン時にユーザーにパスワードのリセットを強制する必要があるシナリオがあります。このために、カスタムの successAuthenticationHandler を使用しています。このハンドラーがしようとしているのは、ログインしているユーザーがパスワードをリセットする必要があるかどうかを確認することだけです。はいの場合、新しい UsernamePasswordAuthenticationToken を作成し、それを SecurityContext に設定します。そして、resetPasswordUrl にリダイレクトします。

これが私の onAuthenticationSuccess メソッドです:

@Override
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
        final Authentication authentication) throws ServletException, IOException {

    final AugmentedUser aUser = (AugmentedUser) SecurityContextHolder.getContext().getAuthentication()
            .getPrincipal();
    System.out.println("In password reset handler.");
    if (authorizationService.isPasswordResetRequired(aUser.getUsername(), aUser.getUsertype())) {
        LOG.debug("Password reset is required.");
        System.out.println("Password reset is required");
        final UsernamePasswordAuthenticationToken authRequest = reAssignUserWithOnlyResetPasswordRole(aUser,
                request);
        SecurityContextHolder.getContext().setAuthentication(authRequest);
        SecurityContextHolder.getContext().getAuthentication();
        System.out.println("User reassinged with only RESET_PASSWORD Authority, redirecting to resetPasswordPage");
        response.sendRedirect(resetPasswordUrl);

        //super.onAuthenticationSuccess(request, response, newAuthentication);
    } else {
        super.onAuthenticationSuccess(request, response, authentication);
    }

}

はいの場合、ログインしたユーザーと同じ資格情報を持つ別の UsernamePasswordAuthenticationToken を作成しますが、彼に単一のロール「RESET_PASSWORD」を割り当てるだけで、他のリンク/URL を押しても何もアクセスできなくなります。

private UsernamePasswordAuthenticationToken reAssignUserWithOnlyResetPasswordRole(final AugmentedUser aUser,
        final HttpServletRequest request) {
    final String username = aUser.getUsername();
    final String password = aUser.getPassword();
    final boolean isEnabled = aUser.isEnabled();
    final boolean isAccountNonExpired = aUser.isAccountNonExpired();
    final boolean isCredentialsNonExpired = aUser.isCredentialsNonExpired();
    final boolean isAccountNonLocked = aUser.isAccountNonLocked();
    LOG.debug("Re-assigning the user: " + username + " with only RESET PASSWORD AUTHORITY");
    System.out.println("Re-assigning the user: " + username + "with only RESET PASSWORD AUTHORITY");
    final Map<String, String> userAttributesMap = new HashMap<String, String>();
    final AugmentedUser userWithResetPasswordRole = new AugmentedUser(username, password, aUser.getUsertype(),
            isEnabled, isAccountNonExpired, isCredentialsNonExpired, isAccountNonLocked,
            createResetPasswordGrantedAuhtority(), userAttributesMap);

    final UsernamePasswordAuthenticationToken authenticationRequest = new UsernamePasswordAuthenticationToken(
            userWithResetPasswordRole, userWithResetPasswordRole.getAuthorities());

    //WebAuthenticationDetails are required for sessionId and ipAddress
    final WebAuthenticationDetails webAuthenticationDetails = new WebAuthenticationDetails(request);
    authenticationRequest.setDetails(webAuthenticationDetails);

    return authenticationRequest;

}

これで、新しい UsernamePasswordAuthenticationToken が RESET パスワード ロールだけで作成されていることがわかります。しかし、resetPasswordURl へのリダイレクトを行っているときに、スプリング フィルターがいくつかのチェックを行い、新しい UsernamePasswordAuthenticationToken を設定した後にユーザーが認証されていないようです。

ログに表示される根本的な原因は次のとおりです。

doAuthentication - Authentication attempt using
org.springframework.security.authentication.dao.DaoAuthenticationProvider
2012-02-15 22:47:20,931 [http-8081-6] DEBUG       org.springframework.security.web.access.ExceptionTranslationFilter    org.springframework.security.web.access.ExceptionTranslationFilter handleException - Authentication exception occurred; redirecting to authentication entry point

org.springframework.security.authentication.BadCredentialsException: Bad credentials
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:67)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:139)
at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:120)

私が間違っているコメントはありますか?

4

1 に答える 1

1

ログ (残りのスタック トレースと前のログ メッセージ) からの詳細なコンテキストなしで言うのは難しいですが、私の最善の推測では、UsernamePasswordAuthenticationToken. 歴史的な理由から、Object役に立たない引数を取ります。

引数が 2 つのバージョンは、ユーザー名と資格情報を取得することになっており、セキュリティ インターセプターの観点からは有効ではない認証されていないトークン (要求用) を作成します。したがって、インターセプターがトークンを再認証しようとしていると推測しています (呼び出し元のスタックトレースから明らかなはずです)。資格情報パラメーターは実際にはパスワードではなく権限のリストであるため、失敗しています。

だから使用:

new UsernamePasswordAuthenticationToken(
        userWithResetPasswordRole, null, userWithResetPasswordRole.getAuthorities());

代わりは。

RESET_PASSWORDまた、デフォルトの構成では認識されないため、処理するカスタムボーターが必要になります。ROLE_または、プレフィックスを使用しますROLE_RESET_PASSWORD

于 2012-02-21T19:06:21.513 に答える