需求:在不影响原来项目的基础上开发一个日志记录插件记录用户操作日志
场景:原项目中使用shiro对用户进行认证和管理,在不影响原来项目的基础上开发一个日志记录插件使用aop记录用户操作日志时,原来项目没有注销的接口(即没有退出的controller)而是通过shiro默认的过滤器实现的退出。
遇到的问题:如何记录用户退出日志
方法:重写shiro的登出过滤器中LogoutFilter中preHandle方法
具体实现:
package com.gisquest.platform.filter;import java.util.Date;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import com.gisquest.platform.aspect.ModulesDesc;
import com.gisquest.platform.common.CommonUtils;
import com.gisquest.platform.common.Constants;
import com.gisquest.platform.common.config.Global;
import com.gisquest.platform.modules.logmgr.vo.SystemLog;@Service
public class CustomLogoutFilter extends LogoutFilter{private static final Logger log = LoggerFactory.getLogger(CustomLogoutFilter.class);@Overridepublic boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {Subject subject = getSubject(request, response);String redirectUrl = getRedirectUrl(request, response, subject);//记录登出日志 SystemLog systemLog = new SystemLog();try {// 设置项目名称String projectName=Global.getConfig("projectName");systemLog.setProjectName(projectName);// 设置业务系统名称String applicationName=Global.getConfig("applicationName");systemLog.setApplicationName(applicationName);// 使用登陆用户名HttpServletRequest request1 =(HttpServletRequest)request ;String userName = request1.getSession().getAttribute("username_") + "";systemLog.setSrcUserName(userName);// 设置IPsystemLog.setSrcAddress(CommonUtils.getIpAddress(request1));//设置地理位置systemLog.setStartTime(Constants.DATEFORMATE.format(new Date()));systemLog.setSrcGeoAddressName(Constants.DQM);systemLog.setDvcAction("注销登陆");systemLog.setOpResult("成功");subject.logout();} catch (SessionException ise) {log.debug("Encountered session exception during logout. This can generally safely be ignored.", ise);systemLog.setOpResult("失败");}ModulesDesc.outPutLogFile(systemLog);issueRedirect(request, response, redirectUrl);return false;}
}
然后将自定义的过滤器放入到ShiroFilterFactoryBean中
<entry key="logout" value-ref="customLogoutFilter"/>
<!-- 安全认证过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><!-- <property name="loginUrl" value="${cas.server.url}?service=${cas.project.url}${adminPath}/cas" /> --><property name="loginUrl" value="${adminPath}/login" /><property name="successUrl" value="${adminPath}?login" /><property name="filters"><map><entry key="cas" value-ref="casFilter"/><entry key="authc" value-ref="formAuthenticationFilter"/><entry key="logout" value-ref="customLogoutFilter"/><!-- 添加自定义退出过滤器,记录用户退出日志 --></map></property><property name="filterChainDefinitions"><ref bean="shiroFilterChainDefinitions"/></property></bean>
注:上述代码只提供一种思路,具体使用的时候注意确保创建的自定义过滤器上的注解@Service能被spring扫描到,业务逻辑按照实际情况添加即可,最后将过滤器放入ShiroFilterFactoryBean
同理记录登录日志的时候也可以通过表单认证过滤器记录用户登录的操作日志,认证通过则跳转到首页,认证不通过则跳转到登陆页面,因此使用shiro可以在表单认证过滤器记录用户登陆信息。