最近整理了一下开发工作,在开发过程中,对用户的登录日志进行记录,是每个系统最基础的工作,faceye使用了acegi作为基础安全框架,也需要对用户登录日志进行记录,查阅了一下网上的资料,有提到使用Spring的ApplicationEvent来做的,主要是做一个ApplicationListener,判断event类型,如果是用户登录成功event,就做日志记录.
看了一下,不太喜欢,于是,打开acegi的源码来看了一下,顺便说一下,这里的源码指的是acegi2.0.
当前使用到的用户登录,主要有两种类型,一种输入用户名密码登录,另一种是根据cookie记录进行登录,所以,要针对这两个Filter进行修改.
通常,我们使用的登录验证器是这个:AuthenticationProcessingFilter
所做的配置为:
<bean id="authenticationProcessingFilter"
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
....
</bean>
那么,在这里,就需要对这个类进行一下重载
在这个类中,要看其父类中的:AbstractProcessingFilter 的doFilterHttp方法
整体 方法如下:
01.public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, 02. ServletException { 03. if (requiresAuthentication(request, response)) { 04. if (logger.isDebugEnabled()) { 05. logger.debug("Request is to process authentication"); 06. } 07. Authentication authResult; 08. try { 09. onPreAuthentication(request, response); 10. authResult = attemptAuthentication(request); 11. } 12. catch (AuthenticationException failed) { 13. // Authentication failed 14. unsuccessfulAuthentication(request, response, failed); 15. return; 16. } 17. // Authentication success 18. if (continueChainBeforeSuccessfulAuthentication) { 19. chain.doFilter(request, response); 20. } 21. successfulAuthentication(request, response, authResult); 22. return; 23. } 24. chain.doFilter(request, response); 25. }
在这里,acegi已经给我们预留了登录成功后置事件接口,successfulAuthentication(...)
在这个方法里面,调用了一个空方法:
onSuccessfulAuthentication(request, response, authResult);
这个方法,在acegi的代码中,是一个懒汉型的,它只会在用户登录成功后被调用,如果用户登录失败,会相应的调用方法:
unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,AuthenticationException failed)
其中对应的后置方法为:
onUnsuccessfulAuthentication(request, response, failed);
这两个方法,都为懒汉型的,要对用户的登录动作(成功,失败)进行记录,只需要重载这两个方法即可.
所以,进行如下实现:
01./** 02. * 03. * 04. * @author:haipeng 05. * @Copy Right:www.faceye.com 06. * @System:www.faceye.com 07. * @Create 2009-7-20 08. * @Package com.faceye.components.security.intercept 09. * @Description: 10. */11.public class UserAuthenticationProcessingFilter extends AuthenticationProcessingFilter 12.{ 13. private IUserService userService = null; 14. private IUserLoginLogService userLoginLogService=null; 15. public IUserLoginLogService getUserLoginLogService() 16. { 17. return userLoginLogService; 18. } 19. 20. public void setUserLoginLogService(IUserLoginLogService userLoginLogService) 21. { 22. this.userLoginLogService = userLoginLogService; 23. } 24. public IUserService getUserService() 25. { 26. return userService; 27. } 28. 29. public void setUserService(IUserService userService) 30. { 31. this.userService = userService; 32. } 33. 34. protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException 35. { 36. if (null != authResult) 37. { 38. String username=null; 39. Object obj=authResult.getPrincipal(); 40. if (obj instanceof UserDetails) { 41. username = ((UserDetails) obj).getUsername(); 42. } else { 43. username = obj.toString(); 44. } 45. WebAuthenticationDetails webDetails = (WebAuthenticationDetails) authResult.getDetails(); 46. String ip = webDetails.getRemoteAddress(); 47. if (StringUtils.isNotEmpty(username)) 48. { 49. User user = (User) ((UserDetailsService) this.getUserService()).loadUserByUsername(username); 50. if (null != user) 51. { 52. UserLoginLog entity = new UserLoginLog(); 53. entity.setUser(user); 54. entity.setIp(ip); 55. this.getUserLoginLogService().save(entity); 56. } 57. } 58. } 59. } 60.}
以此来记录用户的登录日志,当然,还可以实现相应的:
onUnsuccessfulAuthentication(request, response, failed);
与上述代码类似.
同时,用户还可能通过RemeberMe功能进行自动登录,这时,就需要对另外一个进行重载,代码如下:
01./** 02. * 03. * 04. * @author:haipeng 05. * @Copy Right:www.faceye.com 06. * @System:www.faceye.com 07. * @Create 2009-7-20 08. * @Package com.faceye.components.security.intercept 09. * @Description: 10. */11.public class UserRememberMeProcessingFilter extends RememberMeProcessingFilter 12.{ 13. private IUserService userService = null; 14. private IUserLoginLogService userLoginLogService=null; 15. public IUserService getUserService() 16. { 17. return userService; 18. } 19. public void setUserService(IUserService userService) 20. { 21. this.userService = userService; 22. } 23. public IUserLoginLogService getUserLoginLogService() 24. { 25. return userLoginLogService; 26. } 27. public void setUserLoginLogService(IUserLoginLogService userLoginLogService) 28. { 29. this.userLoginLogService = userLoginLogService; 30. } 31. protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, 32. Authentication authResult) { 33. 34. if (null != authResult) 35. { 36. String username=null; 37. Object obj=authResult.getPrincipal(); 38. if (obj instanceof UserDetails) { 39. username = ((UserDetails) obj).getUsername(); 40. } else { 41. username = obj.toString(); 42. } 43. WebAuthenticationDetails webDetails = (WebAuthenticationDetails) authResult.getDetails(); 44. String ip = webDetails.getRemoteAddress(); 45. if (StringUtils.isNotEmpty(username)) 46. { 47. User user = (User) ((UserDetailsService) this.getUserService()).loadUserByUsername(username); 48. if (null != user) 49. { 50. UserLoginLog entity = new UserLoginLog(); 51. entity.setUser(user); 52. entity.setIp(ip); 53. this.getUserLoginLogService().save(entity); 54. } 55. } 56. } 57. } 58.}至此,便可以完整的记录用户的登录日志了.
浙公网安备 33010602011771号