最初のログイン時にユーザーにパスワードのリセットを強制する必要があるシナリオがあります。このために、カスタムの 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)
私が間違っているコメントはありますか?