权限控制是每一个系统都应该有的一个功能,有些只需要简单控制一下就可以了,然而有些却需要进行更加深入和细致的权限控制,尤其是对于一些MIS类系统,基于方法的权限控制就更加重要了。

用反射和自定义注解来实现基于struts2的方法级别的权限控制的主要思想是这样的。
1、先定义一个用于识别在进行action调用的时候标注该方法调用是否需要权限控制,需要什么样的权限的注解类。该注解类一般会包括两个属性,一个是需要的权限,一个是对应的action模块。

2、然后就是在需要进行权限控制的action方法上加上该注解类,并标明其应该拥有的权限和对应的action。这样一来在进行action调用的时候可以实现一个自己定义的interceptor来拦截所有的请求,这样在拦截到请求的时候就可以通过ActionInvocation获取到对应的action类的类文件和对应请求的方法名称,然后利用反射来取得action类文件里面对应的请求方法Method,这样就可通过该Method来判断其是否拥有对应的权限控制注解,即看其是否需要进行权限控制,如果需要进行权限控制,就取得该注解并取得其对应的action名称和需要的权限,然后通过session取得当前的用户,并判断当前用户是否拥有对应的某种权限,如果其拥有该权限则继续往下执行,否则,转到自己处理无权限的机制上去。

下面是一段示例代码:
1、定义一个注解,权限配置

  1. package com.ljq.action;
  2.  
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7.  
  8. /**
  9.  * 定义一个注解,权限配置
  10.  *
  11.  * @author jiqinlin
  12.  *
  13.  */
  14. @Target(ElementType.METHOD)
  15. @Retention(RetentionPolicy.RUNTIME)
  16. public @interface Authority {
  17.  /** 模块 */
  18.  String module();
  19.  
  20.  /** 权限值 */
  21.  String privilege();
  22. }

2、用于拦截请求判断是否拥有权限的拦截器AuthorityInterceptor

  1. package com.ljq.action;
  2.  
  3. import java.lang.reflect.Method;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6.  
  7. import org.apache.log4j.Logger;
  8. import org.apache.struts2.ServletActionContext;
  9.  
  10. import com.opensymphony.xwork2.ActionInvocation;
  11. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
  12.  
  13. /**
  14.  * 用于拦截请求判断是否拥有权限的拦截器
  15.  *
  16.  * @author jiqinlin
  17.  *
  18.  */
  19. @SuppressWarnings("serial")
  20. public class AuthorityInterceptor extends AbstractInterceptor {
  21.  private static final Logger logger=Logger.getLogger(AuthorityInterceptor.class);
  22.  
  23.  public String intercept(ActionInvocation invocation) throws Exception {
  24.   String methodName = invocation.getProxy().getMethod();
  25.   Class clazz=invocation.getAction().getClass(); //获取类对象
  26.   Method currentMethod = clazz.getMethod(methodName);
  27.   //检查Action类AnnotationTest是否含有@Authority注解
  28.   if (currentMethod.isAnnotationPresent(Authority.class)) {
  29.    // 从session里取得当前的用户
  30.    String currentUser = (String) ServletActionContext.getRequest()
  31.     .getSession().getAttribute("currentUser");
  32.    // 取得权限验证的注解
  33.    Authority authority = currentMethod.getAnnotation(Authority.class);
  34.    // 取得当前请求的注解的action
  35.    String module = authority.module();
  36.    // 取得当前请求需要的权限
  37.    String privilege = authority.privilege();
  38.    /**
  39.     * 然后可以在此判断当前用户是否拥有对应的权限,如果没有可以跳到指定的无权限提示页面,
  40.     * 如果拥有则可以 继续往下执行。
  41.     * if (拥有对应的权限) { return invocation.invoke(); }
  42.     * else { return "无权限"; }
  43.     */
  44.    logger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
  45.    logger.info("用户["+currentUser+"]在"+new SimpleDateFormat("yyyy-MM-dd hh24:mm:ss").format(new Date())
  46.      +"调用了["+clazz.getName()+"]类的["+methodName+"]方法,所在模块["+module+"],拥有权限["+privilege+"]。");
  47.    logger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
  48.   }
  49.   return invocation.invoke();
  50.  
  51.  }
  52. }
 

3、需要进行权限控制的Action

  1. package com.ljq.action;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4. import org.apache.struts2.convention.annotation.Namespace;
  5. import org.apache.struts2.convention.annotation.Result;
  6. import org.apache.struts2.convention.annotation.Results;
  7.  
  8. import com.opensymphony.xwork2.ActionSupport;
  9.  
  10. @SuppressWarnings("serial")
  11. @Namespace(value="/")
  12. @Results(value = {
  13.   @Result(name ="success", location = "/index.jsp"),
  14.   @Result(name ="add", location = "/index.jsp"),
  15. })  
  16. @Action(value="action")
  17. public class AnnotationAction extends ActionSupport{
  18.  
  19.  //访问路径:http://localhost:8083/struts2_annotation_auth/action!list.htm
  20.  @Authority(module="annotation", privilege="list")
  21.  public String list() throws Exception {
  22.   System.out.println("-------execute---------");
  23.   return SUCCESS;
  24.  }
  25.   
  26.  //访问路径:http://localhost:8083/struts2_annotation_auth/action!add.htm
  27.  @Authority(module = "annotation", privilege = "add")
  28.  public String add() {
  29.   System.out.println("-------test---------");
  30.   return "add";
  31.  } 
  32.  
  33. }
 

4、在struts2的配置文件里面配置自定义的权限控制拦截器

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE struts PUBLIC
  3.  "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  4.  "http://struts.apache.org/dtds/struts-2.3.dtd">
  5.  
  6. <struts>
  7.  <!--个人发现2.3.4.1注解该项必须配置,否则会有问题,如拦截器无效等。-->
  8.  <constant name="struts.convention.default.parent.package" value="default-package" />
  9.  
  10.  <!-- 可选配置项 -->
  11.  <!-- 是否支持方法动态调用,即action名!方法名,如user!addUser.action调用user.action中的addUser方法.
  12.        不建议使用,这种方法安全性较差
  13.     <constant name="struts.enable.DynamicMethodInvocation" value="false" />-->
  14.     <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
  15.     <constant name="struts.devMode" value="true" />
  16.     <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
  17.     <constant name="struts.i18n.encoding" value="UTF-8" />
  18.     <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
  19.  <constant name="struts.action.extension" value="htm" />
  20.  <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
  21.  <constant name="struts.serve.static.browserCache" value="false" />
  22.  <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
  23.  <constant name="struts.configuration.xml.reload" value="true" />
  24.  <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
  25.  <!-- 配置log4j的日志级别 -->
  26.  <!-- <constant name="log4j.logger.org.apache.struts2.convention" value="DEBUG" /> -->
  27.   
  28.  <package name="default-package" extends="convention-default" abstract="true">
  29.   <!-- 定义拦截器 -->
  30.   <interceptors>
  31.    <!-- 申明自定义的权限控制拦截器 -->
  32.    <interceptor name="authorityInterceptor" class="com.ljq.action.AuthorityInterceptor" />
  33.    <!-- 把自定义的权限控制拦截器和默认的拦截器栈加到新的自定义的拦截器栈 -->
  34.    <interceptor-stack name="myInterceptors">
  35.     <interceptor-ref name="timer" />
  36.     <interceptor-ref name="authorityInterceptor" />
  37.     <interceptor-ref name="defaultStack" />
  38.    </interceptor-stack>
  39.   </interceptors>
  40.   <!-- 指定新的自定义的拦截器栈为默认的拦截器栈,这样自定义的权限控制拦截器就可以发挥作用了 -->
  41.   <default-interceptor-ref name="myInterceptors"></default-interceptor-ref>
  42.  </package>
  43.  
  44. </struts>
 

访问http://localhost:8083/struts2_annotation_auth/action!list.htm,执行结果如下:

  1. [INFO ] [2012-11-29 15:33:26 681]-com.ljq.action.AuthorityInterceptor.44[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. [INFO ] [2012-11-29 15:33:26 682]-com.ljq.action.AuthorityInterceptor.45[http-8083-1] - 用户[null]在2012-11-29 0324:33:26调用了[com.ljq.action.AnnotationAction]类的[list]方法,所在模块[annotation],拥有权限[list]。
  3. [INFO ] [2012-11-29 15:33:26 682]-com.ljq.action.AuthorityInterceptor.47[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4. -------execute---------
  5. [INFO ] [2012-11-29 15:33:27 441]-com.opensymphony.xwork2.interceptor.TimerInterceptor.42[http-8083-1] - Executed action [//action!list] took 765 ms.
 

访问http://localhost:8083/struts2_annotation_auth/action!add.htm,执行结果如下:

  1. [INFO ] [2012-11-29 15:33:53 604]-com.ljq.action.AuthorityInterceptor.44[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. [INFO ] [2012-11-29 15:33:53 605]-com.ljq.action.AuthorityInterceptor.45[http-8083-1] - 用户[null]在2012-11-29 0324:33:53调用了[com.ljq.action.AnnotationAction]类的[add]方法,所在模块[annotation],拥有权限[add]。
  3. [INFO ] [2012-11-29 15:33:53 605]-com.ljq.action.AuthorityInterceptor.47[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4. -------test---------
  5. [INFO ] [2012-11-29 15:33:53 624]-com.opensymphony.xwork2.interceptor.TimerInterceptor.42[http-8083-1] - Executed action [//action!add] took 20 ms.
 

在struts2.3.4.1中使用注解、反射、拦截器实现基于方法的权限控制的更多相关文章

  1. YII2中使用RBAC对模块,控制器,方法的权限控制以及规则的使用

    在使用YII2中自带的RBAC时,需要先配置config/web.php: return [ // ... 'components' => [ 'authManager' => [ 'cl ...

  2. vue中页面跳转拦截器的实现方法

    首先对index.js的router进行配置; export default new Router({ routes: [ { path: '/consultancy', name: 'consult ...

  3. struts2.1笔记03:AOP编程和拦截器概念的简介

    1.AOP编程 AOP编程,也叫面向切面编程(也叫面向方面):Aspect Oriented Programming(AOP),是目前软件开发中的一个热点,也是Spring框架中的一个重要内容.利用A ...

  4. struts2学习笔记(5)---自己定义拦截器

    什么是拦截器? struts2中拦截器分为Struts2定义好的拦截器和自己定义的拦截器. 其作用是在一个Action运行之前进行拦截,在Action运行之后又增加某些操作. 实现原理 当请求一个Ac ...

  5. spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,guava限流,定时任务案例, 发邮件

    本文介绍spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例 集成swagger--对于做前后端分离的项目,后端只需要提供接口访问,swagger提供了接口 ...

  6. springboot中使用过滤器、拦截器、监听器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  7. 在ASP.NET MVC中实现基于URL的权限控制

    本示例演示了在ASP.NET MVC中进行基于URL的权限控制,由于是基于URL进行控制的,所以只能精确到页.这种权限控制的优点是可以在已有的项目上改动极少的代码来增加权限控制功能,和项目本身的耦合度 ...

  8. vue中怎样实现 路由拦截器

    vue中怎样实现 路由拦截器(当用户没有登录的时候,跳转到登录页面,已经登录的时候,不能跳转到登录页,除非后台token失效) 在 我们需要实现这样 一个功能,登录拦截 其实就是 路由拦截,首先在定义 ...

  9. J2EE中的过滤器和拦截器

    过滤器和拦截器的相似之处就是拦截请求,做一些预处理或者后处理. 而过滤器和拦截器的区别在于过滤器是相对HTTP请求而言的,而拦截器是相对Action中的方法的. 过滤器:访问web服务器的时候,对一个 ...

随机推荐

  1. 如何组织一个同时面向 UWP/WPF/.Net Core 控制台的 C# 项目解决方案

    希望写一个小型工具,给自己和需要的人.考虑到代码尽可能的复用,我准备采用 .Net Standard 来编写大多数核心代码,并基于 .Net Core 编写跨平台控制台入口,用 WPF 编写桌面端 U ...

  2. iOS开发之html解析

    使用XPath解析html 可以从此处https://github.com/topfunky/hpple下载工程,将TFHpple.h,TFHpple.m,TFHppleElement.h,TFHpp ...

  3. LeetCode 430. Flatten a Multilevel Doubly Linked List

    原题链接在这里:https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/description/ 题目: You a ...

  4. lapis http verb 处理

    1. 同一个url 包含不同的请求(respond_to  进行解决) // 路由格式 match ,通过respond_to 进行实际的http verb 处理 local lapis = requ ...

  5. 如何批处理多个MySQL文件

    @echo off CHCP 65001 --设置cmd编码for %%i in (E:\sql\*.sql) do (   --多个MySQL  SQL文件的存放目录echo excute %%i ...

  6. 老齐python-基础8(函数)

    1.函数基本概念 2.理解函数 python中一个函数,就是一种映射关系 3.定义函数 #!/usr/bin/env python #coding:utf-8 def add_function(a,b ...

  7. coding 绑定腾讯云开放平台注意事项

    coding升级后需要绑定腾讯云开放平台,按照coding文档的提示操作就好 1.创建腾讯云平台后,不要自定义邮箱和用户名 2.直接绑定原来我们使用的coding账号即可 绑定成功后,邮箱和用户名会自 ...

  8. C语言的补码表示和unsigned及signed的转换

    这东西实际编程时一直无视的,范围小了就换个大点的表示形式,但是总觉得基础知识还是掌握得好,免得到时候用移位运算或类型转换或笔试题时要花时间想. C语言的基本类型有char.int.float.doub ...

  9. Django在Eclipse下配置启动端口号

    首先,在Eclipse左侧树形菜单中找到要更改端口号的项目: 然后,在这里右键选择属性,打开属性界面之后选择Run/Debug Setting,并在其中找到已有的启动项,如果没有可以新建或启动一次. ...

  10. struts2学习(5)拦截器简介以及例子执行过程

    一.拦截器简介: 二.Struts2预定义拦截器&拦截器栈 在执行action之前和之后,拦截器进行了操作: 比如struts-default.xml中就有很多预定义的拦截器:   拦截器栈: ...