zoukankan      html  css  js  c++  java
  • [置顶] 使用struts拦截器+注解实现网络安全要求中的日志审计功能

    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

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


  • 相关阅读:
    time 模块学习
    day 14 自定义模块,常用模块 time .datetime ,time 模块
    day 13 课后作业
    day 12 课后作业
    day 11课后作业
    树状数组最值
    hdu 1059 Dividing bitset 多重背包
    XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship
    最长公共子序列板/滚动 N^2
    Uva 10635
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3279969.html
Copyright © 2011-2022 走看看