基于Struts2拦截器的权限控制

最近闲来无事,自己做了个通过struts2拦截器的权限控制的小例子。主要是通过struts2的核心拦截器机制,不依赖于容器,实现一个可以精确到方法上的细粒度的权限控制。

     该小例子借鉴了网上一些前辈们,还有学界同行们的项目经验,我取其优秀的部分,稍加加工,改造而成,还非常不完善,欢迎大家批评指正。该小例子只供学习交流,无意于商业化中使用,也无意于挑起任何争端。

    下面是一些类的代码,这里可能需要大家对注解比较熟悉,不过不熟悉也不影响,和xml配置文件起的是一样的作用,都是将属性映射成为表的字段。

首先呢,建立一个注解类,名字叫Permission。这个注解类的代码如下

Java代码
package com.zxyg.web.action.privilege;   
  1.   
  2. import java.lang.annotation.ElementType;   
  3. import java.lang.annotation.Retention;   
  4. import java.lang.annotation.RetentionPolicy;   
  5. import java.lang.annotation.Target;   
  6.   
  7. /**  
  8.  * 权限配置 注解类  
  9.  * @author Lan  
  10.  *  
  11.  */  
  12. @Retention(RetentionPolicy.RUNTIME) //注解的存活时间,整个运行时都存活   
  13. @Target(ElementType.METHOD) //此注解表示只能在方法上面有效   
  14. public @interface Permission {   
  15.     /** 模块名 **/  
  16.     String model();   
  17.     /** 权限值 **/  
  18.     String privilegeValue();   
  19. }  
package com.zxyg.web.action.privilege;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 权限配置 注解类
 * @author Lan
 *
 */
@Retention(RetentionPolicy.RUNTIME) //注解的存活时间,整个运行时都存活
@Target(ElementType.METHOD) //此注解表示只能在方法上面有效
public @interface Permission {
	/** 模块名 **/
	String model();
	/** 权限值 **/
	String privilegeValue();
}


这个类,就是将来要在方法上打标记的。

接下来要建立几个跟权限相关的实体类了。
首先是权限实体类,类的代码如下

Java代码
  1. package com.zxyg.bean.privilege;   
  2.   
  3. import javax.persistence.Column;   
  4. import javax.persistence.EmbeddedId;   
  5. import javax.persistence.Entity;   
  6. import javax.persistence.Table;   
  7.   
  8. /**  
  9.  * 系统权限实体  
  10.  * @author Lan  
  11.  *   
  12.  */  
  13. @Entity  
  14. @Table(name="t_systemprivilege")   
  15. public class SystemPrivilege {   
  16.     /** 权限值**/  
  17.     private SystemPrivilegePK id;   
  18.     /** 权限名称**/  
  19.     private String name;   
  20.        
  21.     public SystemPrivilege() {}   
  22.   
  23.     public SystemPrivilege(SystemPrivilegePK id) {   
  24.         this.id = id;   
  25.     }   
  26.   
  27.     public SystemPrivilege(String model, String privilegeValue, String name) {   
  28.         this.id = new SystemPrivilegePK(model, privilegeValue);   
  29.         this.name = name;   
  30.     }   
  31.   
  32.     @EmbeddedId //复合主键的标注   
  33.     public SystemPrivilegePK getId() {   
  34.         return id;   
  35.     }   
  36.   
  37.     public void setId(SystemPrivilegePK id) {   
  38.         this.id = id;   
  39.     }   
  40.   
  41.     @Column(length=20, nullable=false)   
  42.     public String getName() {   
  43.         return name;   
  44.     }   
  45.   
  46.     public void setName(String name) {   
  47.         this.name = name;   
  48.     }   
  49. }  
package com.zxyg.bean.privilege;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

/**
 * 系统权限实体
 * @author Lan
 * 
 */
@Entity
@Table(name="t_systemprivilege")
public class SystemPrivilege {
	/** 权限值**/
	private SystemPrivilegePK id;
	/** 权限名称**/
	private String name;
	
	public SystemPrivilege() {}

	public SystemPrivilege(SystemPrivilegePK id) {
		this.id = id;
	}

	public SystemPrivilege(String model, String privilegeValue, String name) {
		this.id = new SystemPrivilegePK(model, privilegeValue);
		this.name = name;
	}

	@EmbeddedId //复合主键的标注
	public SystemPrivilegePK getId() {
		return id;
	}

	public void setId(SystemPrivilegePK id) {
		this.id = id;
	}

	@Column(length=20, nullable=false)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}


这个类主要包含两个属性,一个是权限值,另外一个是权限的名称,权限值呢,实际也是一个类,这里采用的是复合主键的形式,权限值的实体类代码如下

Java代码
  1. package com.zxyg.bean.privilege;   
  2.   
  3. import javax.persistence.Column;   
  4. import javax.persistence.Embeddable;   
  5.   
  6. /**  
  7.  * 系统权限复合主键类  
  8.  * @author Lan  
  9.  *   
  10.  */  
  11. @Embeddable  
  12. public class SystemPrivilegePK {   
  13.     /** 模块名 **/  
  14.     private String model;   
  15.     /** 权限值 **/  
  16.     private String privilegeValue;   
  17.        
  18.     public SystemPrivilegePK() {}   
  19.   
  20.     public SystemPrivilegePK(String model, String privilegeValue) {   
  21.         this.model = model;   
  22.         this.privilegeValue = privilegeValue;   
  23.     }   
  24.   
  25.     @Column(length=25, name="model")   
  26.     public String getModel() {   
  27.         return model;   
  28.     }   
  29.   
  30.     public void setModel(String model) {   
  31.         this.model = model;   
  32.     }   
  33.   
  34.     @Column(length=20, name="privilegeValue")   
  35.     public String getPrivilegeValue() {   
  36.         return privilegeValue;   
  37.     }   
  38.   
  39.     public void setPrivilegeValue(String privilegeValue) {   
  40.         this.privilegeValue = privilegeValue;   
  41.     }   
  42. }  
package com.zxyg.bean.privilege;

import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 * 系统权限复合主键类
 * @author Lan
 * 
 */
@Embeddable
public class SystemPrivilegePK {
	/** 模块名 **/
	private String model;
	/** 权限值 **/
	private String privilegeValue;
	
	public SystemPrivilegePK() {}

	public SystemPrivilegePK(String model, String privilegeValue) {
		this.model = model;
		this.privilegeValue = privilegeValue;
	}

	@Column(length=25, name="model")
	public String getModel() {
		return model;
	}

	public void setModel(String model) {
		this.model = model;
	}

	@Column(length=20, name="privilegeValue")
	public String getPrivilegeValue() {
		return privilegeValue;
	}

	public void setPrivilegeValue(String privilegeValue) {
		this.privilegeValue = privilegeValue;
	}
}


这个类有两个属性,一个是模块的名称,一个是模块对应的值。其实呢,这里在数据库里面的权限表里存储的就是对某个资源的什么操作,描述名称是什么,比如
role delete 角色删除
意思就是对role这个模块的删除操作,这个呢,就是一个具体的权限。
最后一个实体类就比较简单了,是角色类,类代码如下

Java代码
  1. package com.zxyg.bean.privilege;   
  2.   
  3. import java.util.HashSet;   
  4. import java.util.Set;   
  5.   
  6. import javax.persistence.CascadeType;   
  7. import javax.persistence.Column;   
  8. import javax.persistence.Entity;   
  9. import javax.persistence.FetchType;   
  10. import javax.persistence.GeneratedValue;   
  11. import javax.persistence.Id;   
  12. import javax.persistence.JoinColumn;   
  13. import javax.persistence.JoinTable;   
  14. import javax.persistence.ManyToMany;   
  15. import javax.persistence.Table;   
  16.   
  17. import com.zxyg.bean.organization.Employee;   
  18.   
  19.   
  20. /**  
  21.  * 角色实体  
  22.  * @author Lan  
  23.  *   
  24.  */  
  25. @Entity  
  26. @Table(name="t_role")   
  27. public class Role {   
  28.     /** 主键ID* */  
  29.     private Integer id;   
  30.     /** 角色名称* */  
  31.     private String name;   
  32.     /** 存放权限的集合,角色和权限是多对多的关系 * */  
  33.     private Set<SystemPrivilege> privileges = new HashSet<SystemPrivilege>();   
  34.        
  35.     public Role() {}   
  36.        
  37.     public Role(Integer id) {   
  38.         this.id = id;   
  39.     }   
  40.   
  41.     @Id @GeneratedValue  
  42.     public Integer getId() {   
  43.         return id;   
  44.     }   
  45.   
  46.     public void setId(Integer id) {   
  47.         this.id = id;   
  48.     }   
  49.   
  50.     @Column(length=20, nullable=false)   
  51.     public String getName() {   
  52.         return name;   
  53.     }   
  54.   
  55.     public void setName(String name) {   
  56.         this.name = name;   
  57.     }   
  58.   
  59.     @ManyToMany(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER)   
  60.     @JoinTable(name="t_role_privilege", joinColumns=@JoinColumn(name="roleid"),   
  61.             inverseJoinColumns={@JoinColumn(name="model", referencedColumnName="model"),   
  62.                                 @JoinColumn(name="privilegeValue", referencedColumnName="privilegeValue")}) //中间表,来存放角色、权限的关系   
  63.     public Set<SystemPrivilege> getPrivileges() {   
  64.         return privileges;   
  65.     }   
  66.   
  67.     public void setPrivileges(Set<SystemPrivilege> privileges) {   
  68.         this.privileges = privileges;   
  69.     }   
  70.        
  71.     //定义此方法,方便添加权限   
  72.     public void addPrivilege(SystemPrivilege privilege) {   
  73.         this.privileges.add(privilege);   
  74.     }   
  75. }  
package com.zxyg.bean.privilege;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.zxyg.bean.organization.Employee;


/**
 * 角色实体
 * @author Lan
 * 
 */
@Entity
@Table(name="t_role")
public class Role {
	/** 主键ID* */
	private Integer id;
	/** 角色名称* */
	private String name;
	/** 存放权限的集合,角色和权限是多对多的关系 * */
	private Set<SystemPrivilege> privileges = new HashSet<SystemPrivilege>();
	
	public Role() {}
	
	public Role(Integer id) {
		this.id = id;
	}

	@Id @GeneratedValue
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(length=20, nullable=false)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@ManyToMany(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER)
	@JoinTable(name="t_role_privilege", joinColumns=@JoinColumn(name="roleid"),
			inverseJoinColumns={@JoinColumn(name="model", referencedColumnName="model"),
		                        @JoinColumn(name="privilegeValue", referencedColumnName="privilegeValue")}) //中间表,来存放角色、权限的关系
	public Set<SystemPrivilege> getPrivileges() {
		return privileges;
	}

	public void setPrivileges(Set<SystemPrivilege> privileges) {
		this.privileges = privileges;
	}
	
	//定义此方法,方便添加权限
	public void addPrivilege(SystemPrivilege privilege) {
		this.privileges.add(privilege);
	}
}


这个类就比较简单了,具体看一下其中的关系即可,这里就不多做赘述了。
当你有一个Action类的时候,需要在方法上加标注描述了。举例如下

Java代码
  1. package com.zxyg.web.action.privilege;   
  2.   
  3. import java.io.Serializable;   
  4.   
  5. import javax.annotation.Resource;   
  6.   
  7. import org.springframework.context.annotation.Scope;   
  8. import org.springframework.stereotype.Controller;   
  9.   
  10.   
  11. import com.opensymphony.xwork2.ActionContext;   
  12. import com.zxyg.bean.privilege.Role;   
  13. import com.zxyg.bean.privilege.SystemPrivilege;   
  14. import com.zxyg.bean.privilege.SystemPrivilegePK;   
  15. import com.zxyg.service.privilege.RoleService;   
  16. import com.zxyg.service.privilege.SystemPrivilegeService;   
  17. import com.zxyg.utils.SiteUrl;   
  18. import com.zxyg.web.action.base.BaseSupport;   
  19.   
  20. @Controller @Scope("prototype")   
  21. public class RoleManageAction extends BaseSupport {   
  22.     private static final long serialVersionUID = 1L;   
  23.     @Resource private RoleService roleService;   
  24.     @Resource private SystemPrivilegeService privilegeService;   
  25.     private Role role;   
  26.        
  27.     //接收前端传过来的权限数组,如"角色添加"、"角色删除"等   
  28.     private SystemPrivilegePK[] privileges;   
  29.        
  30.     //接收前端传过来的roleid参数   
  31.     private Integer roleid;   
  32.        
  33.     public Integer getRoleid() {   
  34.         return roleid;   
  35.     }   
  36.   
  37.     public void setRoleid(Integer roleid) {   
  38.         this.roleid = roleid;   
  39.     }   
  40.   
  41.     public SystemPrivilegePK[] getPrivileges() {   
  42.         return privileges;   
  43.     }   
  44.   
  45.     public void setPrivileges(SystemPrivilegePK[] privileges) {   
  46.         this.privileges = privileges;   
  47.     }   
  48.   
  49.     public Role getRole() {   
  50.         return role;   
  51.     }   
  52.   
  53.     public void setRole(Role role) {   
  54.         this.role = role;   
  55.     }   
  56.   
  57.   
  58.     /**  
  59.      * 显示角色添加页面  
  60.      * @return  
  61.      */  
  62.     @Permission(model="role", privilegeValue="insert")   
  63.     public String addUI() {   
  64.         ActionContext.getContext().put("privileges", privilegeService.getScrollData().getResultlist());   
  65.         return "add";   
  66.     }   
  67.        
  68.     /**  
  69.      * 添加角色  
  70.      * @return  
  71.      */  
  72.     @Permission(model="role", privilegeValue="insert")   
  73.     public String add() {   
  74.         for(SystemPrivilegePK id : privileges) {   
  75.             role.addPrivilege(new SystemPrivilege(id));   
  76.         }   
  77.         roleService.save(role);   
  78.         ActionContext context = ActionContext.getContext();   
  79.         context.put("message""添加角色成功");   
  80.         context.put("urladdress", SiteUrl.readUrl("control.role.list"));   
  81.         return "message";   
  82.     }   
  83.        
  84.     /**  
  85.      * 显示角色修改页面  
  86.      * @return  
  87.      */  
  88.     @Permission(model="role", privilegeValue="update")   
  89.     public String updateUI() {   
  90.         role = roleService.find((Serializable)roleid);   
  91.         ActionContext context = ActionContext.getContext();   
  92.         context.put("role", role);   
  93.         context.put("privileges", privilegeService.getScrollData().getResultlist());   
  94.         context.put("selectprivileges", role.getPrivileges());   
  95.         return "edit";   
  96.     }   
  97.        
  98.     /**  
  99.      * 修改角色  
  100.      * @return  
  101.      */  
  102.     @Permission(model="role", privilegeValue="update")   
  103.     public String update() {   
  104.         Role old_role = roleService.find((Serializable)roleid);   
  105.         old_role.setName(role.getName());   
  106.         old_role.getPrivileges().clear();   
  107.         for(SystemPrivilegePK id : privileges) {   
  108.             old_role.addPrivilege(new SystemPrivilege(id));   
  109.         }   
  110.         roleService.update(old_role);   
  111.         ActionContext context = ActionContext.getContext();   
  112.         context.put("message""修改角色成功");   
  113.         context.put("urladdress", SiteUrl.readUrl("control.role.list"));   
  114.         return "message";   
  115.     }   
  116.        
  117.     /**  
  118.      * 删除角色  
  119.      * @return  
  120.      */  
  121.     @Permission(model="role", privilegeValue="delete")   
  122.     public String delete() {   
  123.         roleService.delete((Serializable)roleid);   
  124.         ActionContext context = ActionContext.getContext();   
  125.         context.put("message""删除角色成功");   
  126.         context.put("urladdress", SiteUrl.readUrl("control.role.list"));   
  127.         return "message";   
  128.     }   
  129. }  
package com.zxyg.web.action.privilege;

import java.io.Serializable;

import javax.annotation.Resource;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;


import com.opensymphony.xwork2.ActionContext;
import com.zxyg.bean.privilege.Role;
import com.zxyg.bean.privilege.SystemPrivilege;
import com.zxyg.bean.privilege.SystemPrivilegePK;
import com.zxyg.service.privilege.RoleService;
import com.zxyg.service.privilege.SystemPrivilegeService;
import com.zxyg.utils.SiteUrl;
import com.zxyg.web.action.base.BaseSupport;

@Controller @Scope("prototype")
public class RoleManageAction extends BaseSupport {
	private static final long serialVersionUID = 1L;
	@Resource private RoleService roleService;
	@Resource private SystemPrivilegeService privilegeService;
	private Role role;
	
	//接收前端传过来的权限数组,如"角色添加"、"角色删除"等
	private SystemPrivilegePK[] privileges;
	
	//接收前端传过来的roleid参数
	private Integer roleid;
	
	public Integer getRoleid() {
		return roleid;
	}

	public void setRoleid(Integer roleid) {
		this.roleid = roleid;
	}

	public SystemPrivilegePK[] getPrivileges() {
		return privileges;
	}

	public void setPrivileges(SystemPrivilegePK[] privileges) {
		this.privileges = privileges;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}


	/**
	 * 显示角色添加页面
	 * @return
	 */
	@Permission(model="role", privilegeValue="insert")
	public String addUI() {
		ActionContext.getContext().put("privileges", privilegeService.getScrollData().getResultlist());
		return "add";
	}
	
	/**
	 * 添加角色
	 * @return
	 */
	@Permission(model="role", privilegeValue="insert")
	public String add() {
		for(SystemPrivilegePK id : privileges) {
			role.addPrivilege(new SystemPrivilege(id));
		}
		roleService.save(role);
		ActionContext context = ActionContext.getContext();
		context.put("message", "添加角色成功");
		context.put("urladdress", SiteUrl.readUrl("control.role.list"));
		return "message";
	}
	
	/**
	 * 显示角色修改页面
	 * @return
	 */
	@Permission(model="role", privilegeValue="update")
	public String updateUI() {
		role = roleService.find((Serializable)roleid);
		ActionContext context = ActionContext.getContext();
		context.put("role", role);
		context.put("privileges", privilegeService.getScrollData().getResultlist());
		context.put("selectprivileges", role.getPrivileges());
		return "edit";
	}
	
	/**
	 * 修改角色
	 * @return
	 */
	@Permission(model="role", privilegeValue="update")
	public String update() {
		Role old_role = roleService.find((Serializable)roleid);
		old_role.setName(role.getName());
		old_role.getPrivileges().clear();
		for(SystemPrivilegePK id : privileges) {
			old_role.addPrivilege(new SystemPrivilege(id));
		}
		roleService.update(old_role);
		ActionContext context = ActionContext.getContext();
		context.put("message", "修改角色成功");
		context.put("urladdress", SiteUrl.readUrl("control.role.list"));
		return "message";
	}
	
	/**
	 * 删除角色
	 * @return
	 */
	@Permission(model="role", privilegeValue="delete")
	public String delete() {
		roleService.delete((Serializable)roleid);
		ActionContext context = ActionContext.getContext();
		context.put("message", "删除角色成功");
		context.put("urladdress", SiteUrl.readUrl("control.role.list"));
		return "message";
	}
}


看到这些方法上面的描述了吧,其实最终是要取得这些标注描述再来判断权限的。呵呵,接下来我们就写个拦截器了,这里面就是具体描述,当用户登录后如何和这些方法上的标注相互比对进行权限控制的,拦截器代码如下:

Java代码
  1. package com.zxyg.web.action.privilege;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import org.apache.struts2.ServletActionContext;   
  6.   
  7. import com.opensymphony.xwork2.ActionContext;   
  8. import com.opensymphony.xwork2.ActionInvocation;   
  9. import com.opensymphony.xwork2.interceptor.Interceptor;   
  10. import com.zxyg.bean.organization.Employee;   
  11. import com.zxyg.bean.privilege.Role;   
  12. import com.zxyg.bean.privilege.SystemPrivilege;   
  13. import com.zxyg.bean.privilege.SystemPrivilegePK;   
  14. import com.zxyg.utils.SiteUrl;   
  15.   
  16. /**  
  17.  * 使用拦截器进行系统权限的拦截  
  18.  * @author Lan  
  19.  *   
  20.  */  
  21. public class PermissionInterceptor implements Interceptor {   
  22.     private static final long serialVersionUID = 1L;   
  23.   
  24.     public void destroy() {}   
  25.   
  26.     public void init() {}   
  27.   
  28.     /**  
  29.      * 处理权限拦截  
  30.      */  
  31.     public String intercept(ActionInvocation invocation) throws Exception {   
  32.         Employee employee = (Employee) ServletActionContext.getRequest().getSession().getAttribute("employee"); //取得当前登录的用户   
  33.         if (validate(employee, invocation)) {   
  34.             return invocation.invoke();   
  35.         }   
  36.         ActionContext context = ActionContext.getContext();   
  37.         context.put("message""你没有权限执行该操作");   
  38.         context.put("urladdress", SiteUrl.readUrl("control.center.right"));   
  39.         return "message";   
  40.     }   
  41.   
  42.     /**  
  43.      * 校验控制在方法上的拦截  
  44.      */  
  45.     public boolean validate(Employee employee, ActionInvocation invocation) {   
  46.         String methodName= "execute"//定义默认的访问方法   
  47.         Method currentMethod = null;   
  48.         methodName = invocation.getProxy().getMethod(); //通过actionProxy,得到当前正在执行的方法名   
  49.         try {   
  50.             currentMethod = invocation.getProxy().getAction().getClass().getMethod(methodName, new Class[] {}); //利用反射,通过方法名称得到具体的方法   
  51.             /*Method[] methods = invocation.getProxy().getAction().getClass().getMethods(); //如果不确定方法的具体参数,也可以迭代比较,速度较慢  
  52.             for(Method method : methods ) {  
  53.                 if(method.getName().equals(methodName)) {  
  54.                     currentMethod = method;  
  55.                     break;  
  56.                 }  
  57.             }*/  
  58.         } catch (Exception e) {   
  59.         }   
  60.         if (currentMethod != null && currentMethod.isAnnotationPresent(Permission.class)) {   
  61.             Permission permission = currentMethod.getAnnotation(Permission.class); //得到方法上的Permission注解   
  62.             SystemPrivilege privilege = new SystemPrivilege(new SystemPrivilegePK(permission.model(), permission.privilegeValue())); //通过Permission注解构造出系统权限   
  63.             for (Role role : employee.getRoles()) { //迭代用户所具有的具体权限,如果包含,返回true   
  64.                 if (role.getPrivileges().contains(privilege))    
  65.                     return true;   
  66.             }   
  67.             return false;   
  68.         }   
  69.         return true;   
  70.     }   
  71.   
  72. }  
package com.zxyg.web.action.privilege;

import java.lang.reflect.Method;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.zxyg.bean.organization.Employee;
import com.zxyg.bean.privilege.Role;
import com.zxyg.bean.privilege.SystemPrivilege;
import com.zxyg.bean.privilege.SystemPrivilegePK;
import com.zxyg.utils.SiteUrl;

/**
 * 使用拦截器进行系统权限的拦截
 * @author Lan
 * 
 */
public class PermissionInterceptor implements Interceptor {
	private static final long serialVersionUID = 1L;

	public void destroy() {}

	public void init() {}

	/**
	 * 处理权限拦截
	 */
	public String intercept(ActionInvocation invocation) throws Exception {
		Employee employee = (Employee) ServletActionContext.getRequest().getSession().getAttribute("employee"); //取得当前登录的用户
		if (validate(employee, invocation)) {
			return invocation.invoke();
		}
		ActionContext context = ActionContext.getContext();
		context.put("message", "你没有权限执行该操作");
		context.put("urladdress", SiteUrl.readUrl("control.center.right"));
		return "message";
	}

	/**
	 * 校验控制在方法上的拦截
	 */
	public boolean validate(Employee employee, ActionInvocation invocation) {
		String methodName= "execute"; //定义默认的访问方法
		Method currentMethod = null;
		methodName = invocation.getProxy().getMethod(); //通过actionProxy,得到当前正在执行的方法名
		try {
			currentMethod = invocation.getProxy().getAction().getClass().getMethod(methodName, new Class[] {}); //利用反射,通过方法名称得到具体的方法
			/*Method[] methods = invocation.getProxy().getAction().getClass().getMethods(); //如果不确定方法的具体参数,也可以迭代比较,速度较慢
			for(Method method : methods ) {
				if(method.getName().equals(methodName)) {
					currentMethod = method;
					break;
				}
			}*/
		} catch (Exception e) {
		}
		if (currentMethod != null && currentMethod.isAnnotationPresent(Permission.class)) {
			Permission permission = currentMethod.getAnnotation(Permission.class); //得到方法上的Permission注解
			SystemPrivilege privilege = new SystemPrivilege(new SystemPrivilegePK(permission.model(), permission.privilegeValue())); //通过Permission注解构造出系统权限
			for (Role role : employee.getRoles()) { //迭代用户所具有的具体权限,如果包含,返回true
				if (role.getPrivileges().contains(privilege)) 
					return true;
			}
			return false;
		}
		return true;
	}

}


这些代码呢,其实已经简单的描述了下,就是将用户存储在数据库中间表中的角色对应的权限取出来,在构造出用户想访问的action中方法上的权限描述,相互比对,如果包含,则可以访问,否则没有权限访问。

最后就是struts.xml文件的配置了,配置好拦截器,就都搞定了,配置文件如下

Java代码
  1. <?xml version="1.0" encoding="UTF-8" ?>   
  2. <!DOCTYPE struts PUBLIC   
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">   
  5.   
  6. <struts>   
  7.     <package name="privilege" namespace="/control/role" extends="struts-default">   
  8.         <interceptors>   
  9.             <!-- 定义权限拦截器 -->   
  10.             <interceptor name="permission" class="com.zxyg.web.action.privilege.PermissionInterceptor"/>   
  11.             <!-- 定义拦截器栈,所谓拦截器栈,是指由一个或多个拦截器组成 -->   
  12.             <interceptor-stack name="permissionStack">   
  13.                 <!-- struts2提供的拦截器栈,包含了struts2的很多核心拦截器 -->   
  14.                 <interceptor-ref name="defaultStack" />   
  15.                 <!-- 自己定义的放在最后面,struts2定义的放在前面 -->   
  16.                 <interceptor-ref name="permission" />   
  17.             </interceptor-stack>   
  18.         </interceptors>   
  19.            
  20.         <!-- 为此包下的所有action应用拦截器 -->   
  21.         <default-interceptor-ref name="permissionStack" />   
  22.            
  23.         <global-results>   
  24.             <result name="message">/WEB-INF/page/share/message.jsp</result>   
  25.         </global-results>   
  26.            
  27.         <!-- 显示角色列表 -->   
  28.         <action name="list" class="roleListAction" method="execute">   
  29.             <result name="success">/WEB-INF/page/privilege/rolelist.jsp</result>   
  30.         </action>   
  31.            
  32.         <!-- 角色管理 -->   
  33.         <action name="manage_*" class="roleManageAction" method="{1}">   
  34.             <result name="add">/WEB-INF/page/privilege/addrole.jsp</result>   
  35.             <result name="edit">/WEB-INF/page/privilege/editrole.jsp</result>   
  36.         </action>   
  37.     </package>   
  38. </struts>  
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<package name="privilege" namespace="/control/role" extends="struts-default">
		<interceptors>
			<!-- 定义权限拦截器 -->
			<interceptor name="permission" class="com.zxyg.web.action.privilege.PermissionInterceptor"/>
			<!-- 定义拦截器栈,所谓拦截器栈,是指由一个或多个拦截器组成 -->
			<interceptor-stack name="permissionStack">
				<!-- struts2提供的拦截器栈,包含了struts2的很多核心拦截器 -->
				<interceptor-ref name="defaultStack" />
				<!-- 自己定义的放在最后面,struts2定义的放在前面 -->
				<interceptor-ref name="permission" />
			</interceptor-stack>
		</interceptors>
		
		<!-- 为此包下的所有action应用拦截器 -->
		<default-interceptor-ref name="permissionStack" />
		
		<global-results>
			<result name="message">/WEB-INF/page/share/message.jsp</result>
		</global-results>
		
		<!-- 显示角色列表 -->
		<action name="list" class="roleListAction" method="execute">
			<result name="success">/WEB-INF/page/privilege/rolelist.jsp</result>
		</action>
		
		<!-- 角色管理 -->
		<action name="manage_*" class="roleManageAction" method="{1}">
			<result name="add">/WEB-INF/page/privilege/addrole.jsp</result>
			<result name="edit">/WEB-INF/page/privilege/editrole.jsp</result>
		</action>
	</package>
</struts>


ok,到这里的时候,所有工作就完成了,当用户登录后,就可以进行访问进行权限拦截了的试验了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值