最近整理了一下开发工作,在开发过程中,对用户的登录日志进行记录,是每个系统最基础的工作,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.}

至此,便可以完整的记录用户的登录日志了.

posted on 2009-07-22 09:05  海鹏  阅读(3826)  评论(0编辑  收藏  举报