2012-07-17 43 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 
}