2012-07-17 94 views
2

我有一個spring spring MVC 3.0應用程序,實現了spring security。我正在創建一個小彈出窗口來更改當前登錄用戶的密碼。一切都很好,直到我將表單發佈到以下操作。更改密碼 - Spring Security

@RequestMapping(value = "principalchangepassword" , method = RequestMethod.POST) 
public @ResponseBody String principalchangepassword(Model uiModel, HttpServletRequest httpServletRequest){ 
    Principal principal = (Principal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    StandardStringDigester digester = new StandardStringDigester(); 
    digester.setAlgorithm("SHA-256"); // optionally set the algorithm 
    digester.setStringOutputType("hexadecimal"); 
    digester.setSaltSizeBytes(0); 
    digester.setIterations(1); 
    String digest = digester.digest(httpServletRequest.getParameter("password1")); 
    principal.setPassword(digest.toLowerCase()); 
    principal.merge(); 
    return "Password Updated successfully"; 
} 

當我做一個Ajax調用來更新當前主體的密碼,我得到下面的異常信息。

org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing 

我在做什麼錯?

+0

你能描述一下方法嗎principal.merge? – Jhonathan 2012-07-17 15:03:36

+0

合併用於已存在的實體,即已存儲在數據庫中。如果它是一個全新的校長,我會說principal.persist(); – Binaryrespawn 2012-07-17 15:25:30

回答

2

好了,insted的使用我從語句

(Principal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 

我需要先用ID來明確地從數據庫中LIAD了校長,讓我修改,然後合併得到了校長。這是最後的行動,完美的工作。

@RequestMapping(value = "principalchangepassword" , method = RequestMethod.POST) 
public @ResponseBody String principalchangepassword(Model uiModel, HttpServletRequest httpServletRequest){ 
    Principal principal = (Principal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    Principal me = Principal.findPrincipal(principal.getId()); 
    me.setPassword(httpServletRequest.getParameter("password1")); 
    StandardStringDigester digester = new StandardStringDigester(); 
    digester.setAlgorithm("SHA-256"); // optionally set the algorithm 
    digester.setStringOutputType("hexadecimal"); 
    digester.setSaltSizeBytes(0); 
    digester.setIterations(1); 
    String digest = digester.digest(me.getPassword()); 
    me.setPassword(digest.toLowerCase()); 
    me.merge(); 
    return "Password Updated successfully"; 
} 

希望它可以幫助那裏的人。

0

我發現這個問題,因爲我正在尋找一種方法來創建一個新用戶並設置一個編碼密碼。 Binaryrespawn的答案已經相當不錯了,我只想爲這個問題添加第二個視圖。

所以爲了更改密碼或創建一個新用戶,並沒有必要與Spring進行交互。除了確保您已通過身份驗證(並創建一個擁有權限的新用戶)。

最重要的部分是,PasswordEncoder與Spring中配置的密碼匹配,並且AuthenticationProvider將使用它來比較存儲的密碼和用戶輸入的密碼。

更新密碼的步驟是基本上是:

  1. 負載從數據庫中的現有用戶(通過idusername)。
  2. 獲取春季用於驗證的PasswordEncoder。
  3. 存儲用戶。

創建一個新用戶的步驟是基本上是:

  1. 檢索從前端用戶對象。
  2. 獲取Spring用於驗證的PasswordEncoder
  3. 替換用戶使用編碼版本發送的密碼並將其放回到用戶對象中。
  4. 存儲用戶。

這裏是定義REST端點,以創建一個新用戶的例子:

private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 

@POST 
@Path("user/create") 
@Produces(MediaType.APPLICATION_JSON) 
@Secured("ROLE_ADMIN") 
public User createUser(User user) { 
    if(user.getPassword() == null || user.getPassword().equals("")) { 
     //throw exception... 
    } 
    user.setPassword(passwordEncoder.encode(user.getPassword())); 
    userService.save(user); 
    return user; 
} 
+0

如果你正在尋找一種方法來創建用戶,更改密碼等 - 這可能會有所幫助:我寫了一個實現所有這些流程的項目。看看這裏...讓我知道如果它不明確等https://github.com/OhadR/oAuth2-sample/tree/master/authentication-flows – OhadR 2014-02-28 12:48:11

0

我使用使用BCryptPasswordEncoder春季安全。現在我要做的更改密碼是將用戶提供的現有密碼與DB值進行比較。

BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 
String existingPassword = ... // Password entered by user 
String dbPassword  = ... // Load hashed DB password 

if (passwordEncoder.matches(existingPassword, dbPassword)) { 
    // Encode new password and store it 
} else { 
    // Report error 
}