2013-01-13 3 views
13

私は春のセキュリティを使用してパスワード変更機能を実装しましたが、((UserDetails)プリンシパル).getPassword())はログインしているユーザーに対してnullを返しています。UserDetails getPasswordは、春のセキュリティ3.1では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)プリンシパル).getUsername()正しいログインユーザーを確認できます。 ((UserDetails)プリンシパル).getPassword()nullを返します。

どのようにして((UserDetails)プリンシパル).getPassword()この値を取得しますか?

ありがとうございます!

答えて

25

これを修正するために、このコードブロック(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> 
6

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

+0

これは意味があります。では、これを実行するベストプラクティスは何ですか?私はeraseCredentialsAfterAuthenticationをセキュリティ上のリスクを引き起こす可能性があるため、オフにしたくありません。これを理解するのを助けてくれますか? – texasdude11

2

ユーザーが(一般的に良いことを)認証された後にパスワードがメモリに保持されていないので、明示的にする必要がありますそれを使用するために再ロードしてください。

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 
} 

パスワードをコードする戦略のようなものを心配する必要はありません。そのように:代替し、より柔軟な戦略がAuthenticationManagerのインスタンスを注入し、直接それを使用することです。パスワードはプレーンテキストで保存しないでください。それらはbcrypt or something similarを使用してハッシュする必要があります。

関連する問題