使用Struts2的拦截器和自定义注解方式实现权限控制
<h3><strong>1. 自定义注解的编写:@interface</strong></h3> <p>说明:使用Spring的AOP也可以实现权限的控制,但是经过Spring的AOP方法处理后再交给Struts2时,注意Struts2中上下文参数丢失问题。</p> <p>Struts2的拦截器使用了动态代理,从动态代理类中获取调用方法名并通过invocation.getAction().getClass().getMethod(methodName)获取被调用的方法。然后根据session中保存的用户权限和从方法注解中获取的权限进行判断,看用户是否具有调用该方法的权限进行处理。</p> <p>下面是使用Struts2的Interceptor拦截器实现权限控制的例子:</p> <p>这里我们使用注解为每个Action的方法声明权限。</p> <p>首先创建自定义注解Permission,用于设置权限:</p> <pre> <code class="language-java">@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Permission { /** 权限名称 */ String privilege(); }</code></pre> <p>其中的Permission的module和privilege为模块和模块对应的权限,每个用户登录时都把权限信息保存到session中,方便在拦截器中对权限的判断。</p> <h3><strong>2. Struts2 Interceptor拦截器的编写和配置</strong></h3> <p>1、 编写一个拦截器实现Interceptor接口或者继承AbstractInterceptor</p> <p>接下来最重要的就是编写拦截器对权限进行判断,并作出正确的处理:</p> <pre> <code class="language-java">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("/cms/control/")){ ActionProxy actionProxy = invocation.getProxy(); String methodName = actionProxy.getMethod(); if (StringUtils.isBlank(methodName)) { methodName = "execute";//默认方法 } Class aClass = actionProxy.getAction().getClass(); Method method = aClass.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); if (permission != null) { System.out.println("当前需要的权限为:" + permission.module()); //获取当期执行的Action方法需要的权限 SystemPrivilege methodPrivilege = new SystemPrivilege(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(); } }</code></pre> <p>2、 在struts.xml文件中注册自定义拦截器</p> <p>3、 在需要使用的Action中引用自定义拦截器。</p> <p>在想要设置权限的方法加入自定义的Permission注解用于标识该方法的权限:</p> <pre> <code class="language-java">@Permission(privilege="confirmOrder") public String confirmOrder(){ … }</code></pre> <h3><strong>3. Struts2拦截器原理</strong></h3> <p>AOP面向切面编程和动态代理</p> <p>下面开始讲一下主菜ActionProxy了,在这之前最好先去了解一下动态Proxy的基本知识。</p> <p>ActionProxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。</p> <p>DefaultActionInvocation()->init()->createAction()。</p> <p>最后通过调用</p> <p>ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction() 这里的步骤是先由ActionProxyFactory创建ActionInvocation和ActionProxy。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/0860083d5eecf1896bb728a2d16f8b32.jpg"></p> <p>一个请求在Struts2框架中的处理分为以下几个步骤:</p> <p>1.客户端发出一个指向servlet容器的请求(tomcat);</p> <p>2.这个请求会经过图中的几个过滤器,最后会到达FilterDispatcher过滤器。</p> <p>3.过滤器FilterDispatcher是struts2框架的心脏,在处理用户请求时,它和请求一起相互配合访问struts2的底层框架结构。在web容器启动时,struts2框架会自动加载配置文件里相关参数,并转换成相应的类。</p> <p>如:ConfigurationManager、ActionMapper和ObjectFactory。ConfigurationManager 存有配置文件的一些基本信息,ActionMapper存有action的配置信息。在请求过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。过滤器会通过询问ActionMapper类来查找请求中需要用到的Action。</p> <p>4.如果找到需要调用的Action,过滤器会把请求的处理交给ActionProxy。ActionProxy为Action的代理对象。ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类。</p> <p>5.ActionProxy创建一个ActionInvocation的实例。ActionInvocation在ActionProxy层之下,它表示了Action的执行状态,或者说它控制的Action的执行步骤。它持有Action实例和所有的Interceptor。</p> <p>6.ActionInvocation实例使用命名模式来调用,1. ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。在调用Action的过程前后,涉及到相关拦截器(intercepetor)的调用。</p> <p>7. 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。</p> <p> </p> <p>来自:http://www.linkedkeeper.com/detail/blog.action?bid=60</p> <p> </p>
本文由用户 lyc1976 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!