基于Acegi的权限控制系统跑起来了,但是保存在数据库中的密码还是明文的形式,要将密码加密一下才行哦,要不用户的密码很容易就泄漏出去了。在google上查了很多相关的文章,建议在spring的配置文件中加入以下bean,
<bean class="org.acegisecurity.providers.encoding.Md5PasswordEncoder" id="passwordEncoder"></bean>
搞了半天没有成功,没有那篇文章是介绍的比较详细的,郁闷的是大多文章都是出自某人之手,然后一堆的转载!
本来acegi已经够复杂的,现在又要往里面加入bean就变得更加复杂了。何不自己来做转换呢?这样思路很清晰,而且控制力度加强了。一堆的配置文件不比一堆代码好理解多少。
开始动手了,思路1:
通过改造user的entity类,使得action获得的是加密过的字符串,但是在查找用户名密码的时候hibernate在查询后看见实体类的密码变了,将密码自动update了一次。失败了!
思路2:
1、 在update和save的时候用户在输入密码的时候在将密码进行转换,保存在数据库中的是加密过的字符串。
2、 在登陆的时候将用户输入的密码加密后再跟数据库中的密码进行比较。
3、 扩展authenticationProcessingFilter,因为验证的代码放在authenticationProcessingFilter的doFilter中。
登陆操作:
在authenticationProcessingFilter的obtainPassword方法中,如果password不为空意味着用户进行的是登陆操作,将password加密先。
String id=getBiz().saveUser(Md5Password(user), state);<o:p></o:p> …….<o:p></o:p> protected String obtainPassword(HttpServletRequest request) {<o:p></o:p> String password=request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY);<o:p></o:p> if(password!=null){<o:p></o:p> return MD5.toMD5(request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY));<o:p></o:p> }<o:p></o:p> return password;<o:p></o:p> }<o:p></o:p> <o:p> </o:p> |
<o:p> </o:p>
保存操作:
在useraction中通过页面获得了user的实体类。如果密码不为空那就重新设置一下密码吧
private User Md5Password(User user){<o:p></o:p> if(user.getPassword()!=null){<o:p></o:p> user.setPassword(MD5.toMD5(user.getPassword())); return user;<o:p></o:p> }<o:p></o:p> return user;<o:p></o:p> }<o:p></o:p> |
<o:p> </o:p>
Update操作更简单了:
getBiz().updateUserPassowrd(user.getId(), MD5.toMD5(user.getPassword()), state); |
只是需要将密码加密后传给后台的方法,由后台保存到数据库中。
<o:p> </o:p>
总结:save和update是比较简单的,关键在与登陆的过程获得密码的地方。因为数据库中的密码是加密过的,所以在送用户密码去验证之前要将用户传过来的密码加密一次,以下就是验证密码部分代码。
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,<o:p></o:p> password);<o:p></o:p> setDetails(httpRequest, authRequest);<o:p></o:p> httpRequest.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY,username);<o:p></o:p> authResult = this.getAuthenticationManager().authenticate(authRequest); |
<o:p> </o:p>