JSTL自定义函数完成ACL即时认证
即时认证是指,用户进行查询或更新操作时,判断该用户进行是否对该操作有权限。
这里以判断用户是否有删除权限为例。如果用户有删除权限,即显示该按钮;如果没有删除权限,则不显示该按钮。
1、Manager层的即时认证方法。这里是具体实现即时认证的过程。
package com.lzq.manager.impl; import java.util.Iterator; import java.util.List; import com.lzq.model.ACL; /** * 认证管理 * @author lzq * */ public class ACLManager extends AbstractPageManager { /** * 即时认证 * 判断用户对某模块的某操作的授权(允许或不允许) * @param userId 用户标识 * @param resourceSn 资源标识 * @param permission 权限(C/R/U/D) * @return 允许(true)或不允许(false) */ public boolean hasPermission(int userId, int resourceSn, int permission) { Boolean flag =false; //查找直接授予用户的授权 ACL acl = findACL(ACL.TYPE_USER, userId, resourceSn); if (acl != null) { int yesOrNo = acl.getPermission(permission); //如果是确定的授权 if (yesOrNo != ACL.ACL_NEUTRAL ) { flag = yesOrNo == ACL.ACL_YES ? true:false; return flag; } } //继续查找用户的角色授权 String hql = "select r.id from UsersRoles ur join ur.role r join ur.user u where u.id =? order by ur.orderNo"; List aclIds =getHibernateTemplate().find(hql, userId); //依照角色优先级依次查找其授权 for (Iterator iter = aclIds.iterator(); iter.hasNext();) { Integer rid = (Integer) iter.next(); acl =findACL(ACL.TYPE_ROLE, rid, resourceSn); //一旦发现授权,即刻返回结果 if (acl != null) { flag = acl.getPermission(permission) == acl.ACL_YES ? true: false; return flag; } } return flag; } public boolean hasPermissionBySn(int userId, String resourceSn, int permission) { String hql ="select m.id from Module m where m.sn = ? "; return hasPermission(userId, (Integer)getSession().createQuery(hql).setParameter(0, resourceSn).uniqueResult(), permission); } /** * 根据主体类型、主体标识、资源标识查找ACL实例 * @param principalType * @param principalSn * @param resourceSn * @param permission * @return */ private ACL findACL(String principalType, int principalSn,int resourceSn){ String strSql ="select acl from ACL acl where acl.principalType = ? and acl.principalSn = ? and acl.resourceSn = ?"; ACL acl =(ACL)getSession().createQuery(strSql) .setParameter(0, principalType) .setParameter(1, principalSn) .setParameter(2, resourceSn) .uniqueResult(); return acl; } }
2、定义实现JSTL即时认证的java类,由于程序启动时就要将其加载到内存,该方法必须定义成static类型。
package com.lzq.web; import com.lzq.manager.ACLManager; /** * JSTL函数,主要功能是可以完成权限的即时认证 * @author lzq * */ public class SecurityFunctions { private static ACLManager aclManager; //这个方法不能定义为static,因为这样导致spring无法注入 public void setAclManager(ACLManager aclManager) { SecurityFunctions.aclManager = aclManager; } public static boolean hasPermission(int userId,String resourceSn,int permission){ return aclManager.hasPermissionBySn(userId, resourceSn, permission); } }
3、在web-inf下面新建如下my.tld文件。这里要仿照JSTL标签库里面的tld文件进行编写。
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.1</tlib-version> <short-name>my</short-name> <uri>http://www.lzq.com/functions</uri> <function> <name>hasPermission</name> <function-class>com.lzq.web.SecurityFunctions</function-class> <function-signature>boolean hasPermission(int, java.lang.String,int)</function-signature> <example> <c:if test="${fn:contains(name, searchString)}"> </example> </function> </taglib>
4、在web.xml文件里面进行注册
<!--JSTL注册自定义函数:注册自己编写的方法 --> <jsp-config> <taglib> <taglib-uri>http://www.lzq.com/functions</taglib-uri> <taglib-location>/WEB-INF/my.tld</taglib-location> </taglib> </jsp-config>
5、进行即时认证操作
<c:if test="${my:hasPermission(login.id,'person',3) }"> <td align="center"> <a href="#" onclick="del('person.do?command=del&id=${person.id}')">删除</a> </td> </c:if>
通过动态控制是否显示删除按钮,来控制用户是否有删除的权限。