J2EE项目中出于安全的角度考虑,用户行为审计日志功能必不可少,通过本demo可以实现如下功能:
1.项目中记录审计日志的方法.
2.struts拦截器的基本配置和使用方法.
3.struts拦截器中获得用户访问的类和访问的方法.
4.注解的基本用法,以及在struts拦截器中使用注解.

5.struts拦截器中获得用户访问的IP地址,可扩展对IP进行鉴权功能(允许或限制某些IP).

系统运行一段时间后,通过这些审计日志还可以挖掘的内容:
1.用户行为审计,发现最异常情况及时调整和处理.
2.统计哪些模块访问的频度最高,调整界面把用户访问最高的模块放到显著位置.
3.统计各个功能模块方法的访问时长,有助于我们进行程序性能的优化.
4.用户关联行为分析,优化访问流程,提高用户体验.

项目结构:

功能代码:

AuditLogInterceptor.java(知识点见注释):

package com.tgb.lk.auditlog;

import java.lang.reflect.Method;
import java.util.Date; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.tgb.lk.model.AuditLog; public class AuditLogInterceptor extends MethodFilterInterceptor { @Override
protected String doIntercept(ActionInvocation actioninvocation)
throws Exception {
AuditLog auditLog = new AuditLog(); auditLog.setStartTime(new Date());// 设置开始时间
String result = actioninvocation.invoke();// 递归调用拦截器
auditLog.setEndTime(new Date());// 设置结束时间 String userId = (String) ServletActionContext.getRequest().getSession()
.getAttribute("userId");
auditLog.setUserId(userId);// 设置登录用户的Id,在用户登录时把id保存到session中,这里可扩展判断用户是否登录的验证和权限验证
/*String name = actioninvocation.getInvocationContext().getName();
String methodName = ""; // struts.xml中配置:
// <package name="user" namespace="/user" extends="default">
// <action name="user_*" class="com.tgb.lk.action.UserAction" method="{1}">
//
// 访问地址: http://127.0.0.1:8080/AuditLogDemo/user/user_add
// http://127.0.0.1:8080/AuditLogDemo/user/user_del
if (name != null && name.contains("_")) {
methodName = name.substring(name.indexOf("_") + 1, name.length());
}*/
String methodName = actioninvocation.getProxy().getMethod();
if (methodName.length() > 0) {
Object action = actioninvocation.getAction();
Class clazz = action.getClass();
// 如果设置了注解则读取注解的内容,如果没有设置注解则记录登录的class名
if (clazz.isAnnotationPresent(AuditLogger.class)) {
AuditLogger talClazz = (AuditLogger) clazz
.getAnnotation(AuditLogger.class);
auditLog.setClazz(talClazz.log());
} else {
auditLog.setClazz(clazz.getSimpleName());
} Method method = action.getClass().getMethod(methodName, null);
// 如果设置了注解则读取注解的内容,如果没有设置注解则记录登录的method名
if (method.isAnnotationPresent(AuditLogger.class)) {
AuditLogger alm = (AuditLogger) method
.getAnnotation(AuditLogger.class);
auditLog.setMethod(alm.log());
} else {
auditLog.setMethod(methodName);
}
String ip = ServletActionContext.getRequest().getRemoteAddr();
auditLog.setIp(ip);// 记录登录的IP,这里还可以对IP进行鉴权功能(允许或限制某些IP)
auditLog.setResult(result);// 记录登录时返回的结果. System.out.println(auditLog);
// auditLogService.save(auditLog); //保存入库
}
return result; // 跳转
} }

struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<!-- 日志审计拦截器 -->
<interceptor name="auditlog"
class="com.tgb.lk.auditlog.AuditLogInterceptor" />
<interceptor-stack name="myStack">
<interceptor-ref name="auditlog">
<!--
配置到excludeMethods中的方法将不记录日志
-->
<param name="excludeMethods">testExclude</param>
</interceptor-ref>
<!--
struts默认的拦截器
-->
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack" />
</package> <!-- 注意extends="default" -->
<package name="user" namespace="/user" extends="default">
<action name="user_*" class="com.tgb.lk.action.UserAction" method="{1}">
<result name="add">/index.jsp</result>
<result name="del">/index.jsp</result>
<result name="modify">/index.jsp</result>
<result name="view">/index.jsp</result>
</action>
</package> </struts>

注解类AuditLogger.java:

package com.tgb.lk.auditlog;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target( { java.lang.annotation.ElementType.METHOD,
java.lang.annotation.ElementType.TYPE })
public @interface AuditLogger { public abstract String log(); }

Struts的Action中使用配置:

package com.tgb.lk.action;

import com.tgb.lk.auditlog.AuditLogger;

@AuditLogger(log = "用户管理")
public class UserAction { @AuditLogger(log = "添加用户")
public String add() {
return "add";
} @AuditLogger(log = "删除用户")
public String del() {
return "del";
} @AuditLogger(log = "修改用户")
public String modify() {
return "modify";
} @AuditLogger(log = "浏览用户信息")
public String view() {
return "view";
} }

实体类AuditLog.java

package com.tgb.lk.model;

import java.util.Date;

public class AuditLog {
private int id;
private String userId;
private Date startTime;
private Date endTime;
private String ip;
private String clazz;
private String method;
private String result; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUserId() {
return userId;
} public void setUserId(String userId) {
this.userId = userId;
} public Date getStartTime() {
return startTime;
} public void setStartTime(Date startTime) {
this.startTime = startTime;
} public Date getEndTime() {
return endTime;
} public void setEndTime(Date endTime) {
this.endTime = endTime;
} public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
} public String getClazz() {
return clazz;
} public void setClazz(String clazz) {
this.clazz = clazz;
} public String getMethod() {
return method;
} public void setMethod(String method) {
this.method = method;
} public String getResult() {
return result;
} public void setResult(String result) {
this.result = result;
} @Override
public String toString() {
return "AuditLog [id=" + id + ", userId=" + userId + ", ip=" + ip
+ ", startTime=" + startTime + ", endTime=" + endTime
+ ", clazz=" + clazz + ", method=" + method + ", result="
+ result + "]";
} }

代码下载地址: http://download.csdn.net/detail/lk_blog/6003581

限于本人水平有限,很多地方写的并不完美,望大家不吝赐教,希望在和大家的交流中得到提高.

最新文章

  1. SQL Server 2005 数据库 可疑状态
  2. IE安全分析
  3. 【BZOJ】2795: [Poi2012]A Horrible Poem
  4. jQuery 中 data 方法的实现原理
  5. 界面设计常用CSS属性
  6. 数据挖掘系列(5)使用mahout做海量数据关联规则挖掘
  7. How to control printer orientation(Landscape / Portrait) for an AX report in X++
  8. 深入浅出Spring(五) SpringMVC
  9. 动态规划(二维背包问题):UVAoj 473
  10. 关于Program Size
  11. .net通用权限框架B/S (三)--MODEL层(2)
  12. camel-name-utils 在驼峰风格跟下划线风格之间切换
  13. 【BZOJ 1642】 [Usaco2007 Nov]Milking Time 挤奶时间
  14. MySQL锁详解
  15. bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)
  16. Followme Devops实践之路
  17. elementUI el-select 中disabled设置
  18. MySQL:测试题
  19. JSON字符串解析成JSON数据格式
  20. PyCharm:ModuleNotFoundError: No module named &#39;selenium&#39;

热门文章

  1. Shell入门第一课
  2. C语言自动类型转换
  3. java-下载excel
  4. 1346 - Songs (贪心)
  5. Javascript:getElementsByClassName
  6. 【iOS基础】NSURLConnection
  7. 如何查看Android SDK源码版本
  8. plsql编程中游标的使用
  9. [BZOJ]3643 Phi的反函数
  10. [转]在Linux里设置环境变量的方法