15

Spring Securityを使用してパスワード変更機能を実装しましたが、((UserDetails)principal).getPassword())がログインユーザーに対してnullを返します。

私の記憶が正しければ、これは3.0の初期の段階で機能していました。これは3.1で変更され、ログインしているユーザーの現在のパスワードを取得できなくなりましたか?

以下のコードでは、Webページからユーザーパスワードを入力した現在のパスワードを確認しています。次に、ログインしたユーザーのパスワードが入力したパスワードと一致するかどうかを確認しています。もしそうなら、oldPasswordMatchNewPassword=trueに設定したいと思います。

この機能を実装するにはどうすればよいですか?

@RequestMapping(value = "/account/changePassword.do", method = RequestMethod.POST)
    public String submitChangePasswordPage(
            @RequestParam("oldpassword") String oldPassword,
            @RequestParam("password") String newPassword) {
        Object principal = SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        String username = principal.toString();
        if (principal instanceof UserDetails) {
            username = ((UserDetails) principal).getUsername();
            System.out.println("username: " + username);
            System.out.println("password: "
                    + ((UserDetails) principal).getPassword());
            if (((UserDetails) principal).getPassword() != null) {
                if (((UserDetails) principal).getPassword().equals(oldPassword)) {
                    oldPasswordMatchNewPassword = true;
                }
            }
        }
    if (oldPasswordMatchNewPassword == true) {
        logger.info("Old password matches new password. Password will be updated.");
        changePasswordDao.changePassword(username, newPassword);
        SecurityContextHolder.clearContext();
        return "redirect:home.do";
    } else {
        logger.info("Old password did not match new password. Password will be not be updated.");
        return null;
    }
}

返される値を確認できるように、いくつかのsysout()を配置しました。((UserDetails)principal).getUsername()の場合、正しいログインユーザーを確認できます。((UserDetails)principal).getPassword()nullを返します。

((UserDetails)principal).getPassword()この値を取得するにはどうすればよいですか?

前もって感謝します!

4

3 に答える 3

26

これを修正するために、このコードブロック(erase-credentials = "false")を使用しました。これがエレガントな解決策であるかどうかはわかりませんが、問題は解決しました。

<authentication-manager alias="authenticationManager" erase-credentials="false">
    <!-- authentication-provider user-service-ref="userService" -->
    <authentication-provider>
        <jdbc-user-service data-source-ref="dataSource" />
    </authentication-provider>
</authentication-manager>
于 2013-01-13T21:53:33.007 に答える
6

はい、これはバージョン3.1で変更されました。デフォルトでは、認証が成功すると資格情報がクリアされます。これを防ぐためeraseCredentialsAfterAuthenticationに、でfalseに設定できます。ProviderManager詳細はこちらをご覧ください:http ://static.springsource.org/spring-security/site/docs/3.2.x/reference/core-services.html#core-services-erasing-credentials

于 2013-01-13T12:24:14.363 に答える
2

ユーザーが認証された後、パスワードはメモリに保持されないため(通常は良いことです)、パスワードを使用するには、パスワードを明示的に再ロードする必要があります。別のより柔軟な戦略は、のインスタンスを挿入し、AuthenticationManagerそれを直接使用することです。

String name = SecurityContextHolder.getContext().getAuthentication();

try {
    authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(name, oldPassword));
    // Update password here with your dao
} catch (AuthenticationException e) {
    // Old password was wrong
}

そうすれば、パスワードのエンコード戦略などについて心配する必要はありません。パスワードをプレーンテキストで保存するべきではないことに注意してください。それらはbcryptまたは同様のものを使用してハッシュする必要があります。

于 2013-01-13T22:30:57.977 に答える