今天刚学习了通过自定义注解+拦截器实现权限控制,自己花了点时间整理,发到网站同网友交流分享。
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * 自定义注解 * @author grace * */ @Retention(RetentionPolicy.RUNTIME) public @interface Limit{ String module(); //模块名称 String privilege(); //操作名称 }
#权限组表 CREATE TABLE `sys_role` ( `id` varchar(36), #编号 `remark` TEXT, #备注 `name` VARCHAR(100) DEFAULT NULL, #名称 PRIMARY KEY (`id`) )
#操作表 CREATE TABLE sys_popedom ( popedomModule VARCHAR(30), #模块名称 popedomPrivilege VARCHAR(30), #操作名称 sort INTEGER(11), #排序 title VARCHAR(200), #提示 popedomName VARCHAR(200), #标题 remark TEXT, #说明 PRIMARY KEY(popedomModule,popedomPrivilege) )
#操作权限表 CREATE TABLE sys_popedom_privilege ( roleId VARCHAR(36), #权限组编号 popedomModule VARCHAR(30), #模块名称 popedomPrivilege VARCHAR(30), #操作名称 PRIMARY KEY(roleId,popedomModule,popedomPrivilege) )
/* * SysRole:权限组表 */ @SuppressWarnings("serial") public class SysRole implements java.io.Serializable { private String id; private String name; private String remark; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
/* * 操作表 */ @SuppressWarnings("serial") public class SysPopedom implements java.io.Serializable{ /* * CREATE TABLE sys_popedom ( popedomModule VARCHAR(30), #模块名称 popedomPrivilege VARCHAR(30), #操作名称 sort INTEGER(11), #排序 title VARCHAR(200), #提示 popedomName VARCHAR(200), #标题 remark TEXT, #说明 PRIMARY KEY(popedomModule,popedomPrivilege) ) */ private SysPopedomId id;//主键 OID private Integer sort; private String title; private String popedomName; private String remark; public SysPopedomId getId() { return id; } public void setId(SysPopedomId id) { this.id = id; } public Integer getSort() { return sort; } public void setSort(Integer sort) { this.sort = sort; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPopedomName() { return popedomName; } public void setPopedomName(String popedomName) { this.popedomName = popedomName; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
/** * 操作表中的联合主键类 * @author grace * */ @SuppressWarnings("serial") public class SysPopedomId implements java.io.Serializable { private String popedomModule; private String popedomPrivilege; public String getPopedomModule() { return popedomModule; } public void setPopedomModule(String popedomModule) { this.popedomModule = popedomModule; } public String getPopedomPrivilege() { return popedomPrivilege; } public void setPopedomPrivilege(String popedomPrivilege) { this.popedomPrivilege = popedomPrivilege; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((popedomModule == null) ? 0 : popedomModule.hashCode()); result = prime * result + ((popedomPrivilege == null) ? 0 : popedomPrivilege.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final SysPopedomId other = (SysPopedomId) obj; if (popedomModule == null) { if (other.popedomModule != null) return false; } else if (!popedomModule.equals(other.popedomModule)) return false; if (popedomPrivilege == null) { if (other.popedomPrivilege != null) return false; } else if (!popedomPrivilege.equals(other.popedomPrivilege)) return false; return true; } }
/** * 操作权限表 * @author grace * */ @SuppressWarnings("serial") public class SysPopedomPrivilege implements java.io.Serializable { /* * CREATE TABLE sys_popedom_privilege * ( * roleId VARCHAR(36), #权限组编号 * popedomModule VARCHAR(30), #模块名称 * popedomPrivilege VARCHAR(30), #操作名称 * PRIMARY KEY(roleId,popedomModule,popedomPrivilege) * ) */ private SysPopedomPrivilegeId id; public SysPopedomPrivilegeId getId() { return id; } public void setId(SysPopedomPrivilegeId id) { this.id = id; } }
/** * 操作权限表的联合主键类 * @author grace * */ @SuppressWarnings("serial") public class SysPopedomPrivilegeId implements java.io.Serializable { private String roleId; private String popedomModule; private String popedomPrivilege; public String getRoleId() { return roleId; } public void setRoleId(String roleId) { this.roleId = roleId; } public String getPopedomModule() { return popedomModule; } public void setPopedomModule(String popedomModule) { this.popedomModule = popedomModule; } public String getPopedomPrivilege() { return popedomPrivilege; } public void setPopedomPrivilege(String popedomPrivilege) { this.popedomPrivilege = popedomPrivilege; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((popedomModule == null) ? 0 : popedomModule.hashCode()); result = prime * result + ((popedomPrivilege == null) ? 0 : popedomPrivilege.hashCode()); result = prime * result + ((roleId == null) ? 0 : roleId.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final SysPopedomPrivilegeId other = (SysPopedomPrivilegeId) obj; if (popedomModule == null) { if (other.popedomModule != null) return false; } else if (!popedomModule.equals(other.popedomModule)) return false; if (popedomPrivilege == null) { if (other.popedomPrivilege != null) return false; } else if (!popedomPrivilege.equals(other.popedomPrivilege)) return false; if (roleId == null) { if (other.roleId != null) return false; } else if (!roleId.equals(other.roleId)) return false; return true; } }
import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; /** * 自定义拦截器 * @author grace * */ @SuppressWarnings("serial") public class LimitInterceptor extends MethodFilterInterceptor{ public String doIntercept(ActionInvocation invocation) throws Exception { //获取请求的action对象 Object action=invocation.getAction(); //获取请求的方法的名称 String methodName=invocation.getProxy().getMethod(); //获取action中的方法的封装类(action中的方法没有参数) Method method=action.getClass().getMethod(methodName, null); //获取request对象 HttpServletRequest request=ServletActionContext.getRequest(); //检查注解 boolean flag=isCheckLimit(request,method); if(!flag){ //没有权限,通过struts2转到事先定义好的页面 return "popmsg_popedom"; } //有权限,可以调用action中的方法 String returnvalue=invocation.invoke(); return returnvalue; } public boolean isCheckLimit(HttpServletRequest request, Method method) { if(method==null){ return false; } //获取当前的登陆用户 SysUser sysUser=SessionUtils.getSysUserFormSession(request); if(sysUser==null){ return false; } //如果用户的权限组为空 if(sysUser.getSysRole()==null){ return false; } //获取当前登陆用户的权限组id String roleId=sysUser.getSysRole().getId(); //处理注解 /* * @Limit(module="group",privilege="list") public String list(){ .... } */ //判断用户请求的method上面是否存在注解 boolean isAnnotationPresent= method.isAnnotationPresent(Limit.class); //不存在注解 if(!isAnnotationPresent){ return false; } //存在注解,拿到由Limit类写的注解 Limit limit=method.getAnnotation(Limit.class); //获取注解上的值 String module=limit.module(); //模块名称 String privilege=limit.privilege(); //操作名称 /** * 如果登陆用户的权限组id+注解上的@Limit(module="group",privilege="list") * * 在sys_popedom_privilege表中存在 flag=true; * * 在sys_popedom_privilege表中不存在 flag=false; */ boolean flag=false; //通过自己封装的方法拿到操作权限的业务层对象 ISysPopedomPrivilegeService sysPopedomPrivilegeService= (ISysPopedomPrivilegeService)ServiceProvinder.getService(ISysPopedomPrivilegeService.SERVICE_NAME); //查询sys_popedom_privilege表中的所有的数据 //因为后面用到二级缓存,因此这里直接查询出所有的操作权限,而不是通过登陆用户的权限组来查询 List<SysPopedomPrivilege> list=sysPopedomPrivilegeService.findAllSysPopedomPrivileges(); if(list!=null&&list.size()>0){ for(int i=0;i<list.size();i++){ SysPopedomPrivilege s=list.get(i); if(s!=null){ //判断登陆用户是否拥有该方法的权限:如果登陆用户的roleId和登陆用户访问的方法 //的注释中的module和privilege(例如@Limit(module="group",privilege="list")),这三个字段 //在sys_popedom_privilege表中有记录与之对应,则代表该用户拥有权限访问此方法 if(roleId.equals(s.getId().getRoleId())&&module.equals(s.getId().getPopedomModule()) &&privilege.equals(s.getId().getPopedomPrivilege())){ flag=true; break; } } } } return flag; } }
<interceptors> <!-- 声明拦截器 --> <interceptor name="limitInterceptor" class="cn.grace.interceptor.LimitInterceptor"></interceptor> <interceptor-stack name="limitStack"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="limitInterceptor"> <!-- 配置不被拦截的方法 --> <param name="excludeMethods">isLogin,logout,top,left</param> </interceptor-ref> </interceptor-stack> </interceptors> <!-- struts2运行时,执行的拦截器栈 --> <default-interceptor-ref name="limitStack" /> <global-results> <!-- 转发到没有权限的页面 --> <result name="popmsg_popedom">/WEB-INF/page/popmsg_popedom.jsp</result> </global-results>
import cn.grace.annotation.Limit; public class testUserAction { /** 用户添加页面 */ @Limit(module="user",privilege="add") public String add(){ return "add"; } /** 用户添加 **/ @Limit(module="user",privilege="save") public String save(){ return "save"; } /** 用户删除 **/ @Limit(module="user",privilege="delete") public String delete(){ return "delete"; } /** 用户修改页面 **/ @Limit(module="user",privilege="edit") public String edit() { return "edit"; } /** 用户修改 **/ @Limit(module="user",privilege="update") public String update() { return "update"; } /** 用户列表 (查询) */ @Limit(module="user",privilege="list") public String list() { return "list"; } }至此,权限控制实现完毕。
1.系统管理的权限id(roleId)为:8af0897545e4c91b0145e4cd385d0002;而在sys_popedom_privilege表中,roleId为:8af0897545e4c91b0145e4cd385d0002,拥有所有模块和操作,则系统管理员拥有所有模块的所有操作权限。
2.部门经理的权限id(roleId)为:8af09d7845fe6ef90145fe70a0a80001;而在sys_popedom_privilege表中,roleId为:8af09d7845fe6ef90145fe70a0a80001,拥有部门模块的所有操作(9个),则部门经理拥有部门模块的所有9个操作权限,但没有其他(例如city和code模块)模块的操作权限。
3.小明的权限id(roleId)为:8af0897545e4c91b0145e4cd65b30003;而在sys_popedom_privilege表中,roleId为:8af0897545e4c91b0145e4cd65b30003,仅拥有部门模块的部分操作(比部门经理比少了list和edit操作),则小明拥有部门模块下的部分操作权限。如下图,其中roleId为8af0897545e4c91b0145e4cd65b30003对应的模块和操作只有下图前7行。