0%
这是一片思考的空间 -- arthinking
Spring 重构&代码整洁之道 软件设计 JVM 并发编程 数据结构与算法 分布式 存储 网络 微服务 设计模式
Java技术栈 - 涉及Java技术体系

使用Struts2的拦截器和自定义注解方式实现权限控制

技能修炼:

在S2SH集成环境中使用Struts2的Interceptor拦截器实现权限的控制。

准备知识:

 自定义注解的编写: @interface **** Struts2 Interceptor拦截器的编写和配置 1、 编写一个拦截器实现Interceptor接口或者继承AbstractInterceptor 2、 在struts.xml文件中注册自定义拦截器 3、 在需要使用的Action中引用自定义拦截器。 ****★ 了解Struts2拦截器原理 AOP面向切面编程和动态代理

提示

使用Spring的AOP也可以实现权限的控制,但是经过Spring的AOP方法处理后再交给Struts2时,注意Struts2中上下文参数丢失问题。

Struts2的拦截器使用了动态代理,从动态代理类中获取调用方法名并通过invocation.getAction().getClass().getMethod(methodName)获取被调用的方法。然后根据session中保存的用户权限和从方法注解中获取的权限进行判断,看用户是否具有调用该方法的权限进行处理。

下面是使用Struts2的Interceptor拦截器实现权限控制的例子

这里我们使用注解为每个Action的方法声明权限。

首先创建自定义注解Permission,用于设置权限:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission {
/** 模块名称 /
String module();
/
* 权限名称 */
String privilege();
}

其中的Permission的module和privilege为模块和模块对应的权限,每个用户登录时都把权限信息保存到session中,方便在拦截器中对权限的判断。

在想要设置权限的方法加入自定义的Permission注解用于标识该方法的权限:

@Permission(module="order", privilege="confirmOrder")
public String confirmOrder(){…}

接下来最重要的就是编写拦截器对权限进行判断,并作出正确的处理:

public class PrivilegeInterceptor extends AbstractInterceptor {

private static final long serialVersionUID = 742285864455102141L;

/**
 * 1、通过动态代理类和反射机制获取调用的方法
 * 2、获取方法的Permission注解
 * 3、获取Permission中包含的权限信息(构造SystemPrivilege权限类)
 * 4、和用户的权限信息进行对比(PrivilegeGroup中的SystemPrivilege)判断用户的权限
 */
@Override
public String intercept(ActionInvocation invocation) throws Exception {

	HttpServletRequest request = ServletActionContext.getRequest();
	if(WebUtil.getRequestURI(request).startsWith("/MusicalInstrumentsStore/control/")){
		String methodName = invocation.getProxy().getMethod();
		Method method = invocation.getAction().getClass().getMethod(methodName);			
		if(method!=null && method.isAnnotationPresent(Permission.class)){
			System.out.println("Call the Action Method:" + method.toString());
			//获取当期执行的Action上的注解
			Permission permission = method.getAnnotation(Permission.class);
			System.out.println("当前需要的权限为:" + permission.module());
			//获取当期执行的Action方法需要的权限
			SystemPrivilege methodPrivilege = new SystemPrivilege(new SystemPrivilegePK(permission.module(),permission.privilege()));
			//WebUtil.getEmployee(request) 方法是从session中获取保存的employee信息,包括权限集合
			Employee employee = WebUtil.getEmployee(request);
			//循环判断用户是否具有该权限,如果有则继续执行,否则返回提示视图
			for(PrivilegeGroup group : employee.getGroups()){
				if(group.getPrivileges().contains(methodPrivilege)){
					return invocation.invoke();
				}
			}
			System.out.println("权限不足");
			return "privilegemessage";
		}
		System.out.println("未设置权限");
		return invocation.invoke();
	}
	System.out.println("所有权限");
	return invocation.invoke();
}

}

欢迎关注我的其它发布渠道

订阅IT宅
内功修炼
Java技术栈
Java架构杂谈是IT宅精品文章公众号,欢迎订阅:
📄 网络基础知识:两万字长文50+张趣图带你领悟网络编程的内功心法 📄 HTTP发展史:三万长文50+趣图带你领悟web编程的内功心法 📄 HTTP/1.1:可扩展,可靠性,请求应答,无状态,明文传输 📄 HTTP/1.1报文详解:Method,URI,URL,消息头,消息体,状态行 📄 HTTP常用请求头大揭秘 📄 HTTPS:网络安全攻坚战 📄 HTTP/2:网络安全传输的快车道 📄 HTTP/3:让传输效率再一次起飞 📄 高性能网络编程:图解Socket核心内幕以及五大IO模型 📄 高性能网络编程:三分钟短文快速了解信号驱动式IO 📄 高性能网络编程:彻底弄懂IO复用 - IO处理杀手锏,带您深入了解select,poll,epoll 📄 高性能网络编程:异步IO:新时代的IO处理利器 📄 高性能网络编程:网络编程范式 - 高性能服务器就这么回事 📄 高性能网络编程:性能追击 - 万字长文30+图揭秘8大主流服务器程序线程模型
📄 Java内存模型:如果有人给你撕逼Java内存模型,就把这些问题甩给他 📄 一文带你彻底理解同步和锁的本质(干货) 📄 AQS与并发包中锁的通用实现 📄 ReentrantLock介绍与使用 📄 ReentrantReadWriteLock介绍与使用 📄 ReentrantLock的Condition原理解析 📄 如何优雅的中断线程 📄 如何优雅的挂起线程 📄 图解几个好玩的并发辅助工具类 📄 图解BlockingQueue阻塞队列
📄 消息队列那么多,为什么建议深入了解下RabbitMQ? 📄 高并发异步解耦利器:RocketMQ究竟强在哪里? 📄 Kafka必知必会18问:30+图带您看透Kafka
📄 洞悉MySQL底层架构:游走在缓冲与磁盘之间 📄 SQL运行内幕:从执行原理看调优的本质 📄 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法