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

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

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

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

package com.ljq.action;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 定义一个注解,权限配置
 *
 * @author jiqinlin
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {
 /** 模块 */
 String module();
 
 /** 权限值 */
 String privilege();
}

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

package com.ljq.action;
 
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 
/**
 * 用于拦截请求判断是否拥有权限的拦截器
 *
 * @author jiqinlin
 *
 */
@SuppressWarnings("serial")
public class AuthorityInterceptor extends AbstractInterceptor {
 private static final Logger logger=Logger.getLogger(AuthorityInterceptor.class);
 
 public String intercept(ActionInvocation invocation) throws Exception {
  String methodName = invocation.getProxy().getMethod();
  Class clazz=invocation.getAction().getClass(); //获取类对象
  Method currentMethod = clazz.getMethod(methodName);
  //检查Action类AnnotationTest是否含有@Authority注解
  if (currentMethod.isAnnotationPresent(Authority.class)) {
   // 从session里取得当前的用户
   String currentUser = (String) ServletActionContext.getRequest()
    .getSession().getAttribute("currentUser");
   // 取得权限验证的注解
   Authority authority = currentMethod.getAnnotation(Authority.class);
   // 取得当前请求的注解的action
   String module = authority.module();
   // 取得当前请求需要的权限
   String privilege = authority.privilege();
   /**
    * 然后可以在此判断当前用户是否拥有对应的权限,如果没有可以跳到指定的无权限提示页面,
    * 如果拥有则可以 继续往下执行。
    * if (拥有对应的权限) { return invocation.invoke(); }
    * else { return "无权限"; }
    */
   logger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
   logger.info("用户["+currentUser+"]在"+new SimpleDateFormat("yyyy-MM-dd hh24:mm:ss").format(new Date())
     +"调用了["+clazz.getName()+"]类的["+methodName+"]方法,所在模块["+module+"],拥有权限["+privilege+"]。");
   logger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
  }
  return invocation.invoke();
 
 }
}
 

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

package com.ljq.action;
 
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
 
import com.opensymphony.xwork2.ActionSupport;
 
@SuppressWarnings("serial")
@Namespace(value="/")
@Results(value = {
  @Result(name ="success", location = "/index.jsp"),
  @Result(name ="add", location = "/index.jsp"),
})  
@Action(value="action")
public class AnnotationAction extends ActionSupport{
 
 //访问路径:http://localhost:8083/struts2_annotation_auth/action!list.htm
 @Authority(module="annotation", privilege="list")
 public String list() throws Exception {
  System.out.println("-------execute---------");
  return SUCCESS;
 }
  
 //访问路径:http://localhost:8083/struts2_annotation_auth/action!add.htm
 @Authority(module = "annotation", privilege = "add")
 public String add() {
  System.out.println("-------test---------");
  return "add";
 } 
 
}
 

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

<?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>
 <!--个人发现2.3.4.1注解该项必须配置,否则会有问题,如拦截器无效等。-->
 <constant name="struts.convention.default.parent.package" value="default-package" />
 
 <!-- 可选配置项 -->
 <!-- 是否支持方法动态调用,即action名!方法名,如user!addUser.action调用user.action中的addUser方法.
       不建议使用,这种方法安全性较差
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />-->
    <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
    <constant name="struts.devMode" value="true" />
    <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
 <constant name="struts.action.extension" value="htm" />
 <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
 <constant name="struts.serve.static.browserCache" value="false" />
 <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
 <constant name="struts.configuration.xml.reload" value="true" />
 <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
 <!-- 配置log4j的日志级别 -->
 <!-- <constant name="log4j.logger.org.apache.struts2.convention" value="DEBUG" /> -->
  
 <package name="default-package" extends="convention-default" abstract="true">
  <!-- 定义拦截器 -->
  <interceptors>
   <!-- 申明自定义的权限控制拦截器 -->
   <interceptor name="authorityInterceptor" class="com.ljq.action.AuthorityInterceptor" />
   <!-- 把自定义的权限控制拦截器和默认的拦截器栈加到新的自定义的拦截器栈 -->
   <interceptor-stack name="myInterceptors">
    <interceptor-ref name="timer" />
    <interceptor-ref name="authorityInterceptor" />
    <interceptor-ref name="defaultStack" />
   </interceptor-stack>
  </interceptors>
  <!-- 指定新的自定义的拦截器栈为默认的拦截器栈,这样自定义的权限控制拦截器就可以发挥作用了 -->
  <default-interceptor-ref name="myInterceptors"></default-interceptor-ref>
 </package>
 
</struts>
 

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

[INFO ] [2012-11-29 15:33:26 681]-com.ljq.action.AuthorityInterceptor.44[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
[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]。
[INFO ] [2012-11-29 15:33:26 682]-com.ljq.action.AuthorityInterceptor.47[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
-------execute---------
[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,执行结果如下:

[INFO ] [2012-11-29 15:33:53 604]-com.ljq.action.AuthorityInterceptor.44[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
[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]。
[INFO ] [2012-11-29 15:33:53 605]-com.ljq.action.AuthorityInterceptor.47[http-8083-1] - ++++++++++++++++++++++++++++++++++++++++++++++++++++++
-------test---------
[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. 解决遇到Linux网络配置,从熟悉网络配置文件入手

    如果接触过Linux,网络配置是一个比较棘手的问题.但是Linux是文件为基础来构建的系统,包括我们windows中设备,Linux也视为文件.所以只要我们明白文件的作用.就能对Linux更加的熟悉, ...

  2. matplotlib ----- 多子图, subplots

    这一篇讲的比较详细. http://matplotlib.org/examples/pylab_examples/subplots_demo.html 官方文档给出的subplots用法, http: ...

  3. 一张elixir生产环境部署的图

  4. android 自己定义checkbox 背景图无效的问题

    http://blog.csdn.net/zuolongsnail/article/details/7106586  正常的定义能够參考这个网址  可是我參考它以后发现我执行时候 根本不工作嘛  结果 ...

  5. MySQL的安装配置教程

    1. 官网下载ZIP压缩版本(本人电脑是64位的) x64bit MySQL Community 2. 解压到E:\SoftwareFiles\mysql-5.7.11-winx64 3. 在E:\S ...

  6. 利用 netsh 给 mysql 开启多端口监听

    利用 netsh 给 mysql 开启多端口监听 标题党,实际并不是真的多端口监听,只是端口转发而已. 由于某种特殊原因需要 mysql 服务器多个端口监听. mysql 服务器本身是不支持的,但可以 ...

  7. [LeetCode系列]爬梯问题的递归解法转换为迭代解法

    有一个n阶的梯子, 你每次只能爬1阶或2阶, 请问共有多少种登顶的爬法?(正好爬完n阶, 不能多也不能少) 本题最优解是直接套用菲波那切数列即可(因为菲波那切数列的第n个元素正好等于第n-1个元素和第 ...

  8. webstorm配置scss的小结

    1)安装ruby 2)安装sass 3)配置webstorm 打开webstrom ->file->setting->Tools->file watcher 添加scss pr ...

  9. AT指令(二)

    1.常用操作1.1 AT命令解释:检测 Module 与串口是否连通,能否接收 AT 命令:命令格式:AT<CR>命令返回:OK (与串口通信正常)             (无返回,与串 ...

  10. GOF23设计模式之组合模式(composite)

    一.组合模式概述 将对象组合成树状结构以表示“部分和整体”层次结构,使得客户可以统一的调用叶子对象和容器对象. (1)组合模式的使用场景   把部分和整体的关系用树形结构来表示,从而使客户端可以使用统 ...