日期:2014-05-16  浏览次数:20346 次

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>