• ACL授权实例


    上一篇关于ACL的文章中:位运算实现ACL授权与认证过程的原理解析,我们学习了通过位运算实现ACL授权与认证的原理核心,今天我们一起来看授权的实例。

    实现的功能很简单:打开授权界面时,加载已授权信息。通过点击授权界面上面的复选框,实现授权与取消授权。


    下面是Manager层的实现:

    package com.lzq.manager.impl;
    
    import java.util.List;
    import com.lzq.model.ACL;
    
    /**
     * 主体授权管理实现
     * @author lzq
     *
     */
    public class ACLManager extends AbstractPageManager {
    
    	/**
    	 * 授权过程
    	 * 添加或更新授权操作
    	 * @param principalType 主体类型  用户或角色
    	 * @param principalSn 主体标识  用户Id或角色Id
    	 * @param resourceSn 资源标识  模块Id
    	 * @param permission 权限  C/R/U/D 0 1 2 3 
    	 * @param yes 是否允许,true表示允许授权;false表示不允许授权
    	 */
    	public void addOrUpdatePermission(String principalType, int principalSn,
    			int resourceSn, int permission, boolean yes) {
    		//根据主体标识和资源标识查找ACL实例
    		ACL acl = findACL(principalType, principalSn, resourceSn);
    		
    		//如果存在ACL实例,则更新其授权
    		if (acl != null) {
    			acl.setPermission(permission, yes);
    			getHibernateTemplate().update(acl);
    			return;
    		}
    		
    		//如果不存在ACL实例,则创建ACL实例
    		acl = new ACL();
    		acl.setPrincipalType(principalType);
    		acl.setPrincipalSn(principalSn);
    		acl.setResourceSn(resourceSn);
    		acl.setPermission(permission, yes);
    		getHibernateTemplate().save(acl);
    	}
    
    	/**
    	 * 删除授权
    	 * @param principalType 主体类型
    	 * @param principalSn 主体标识
    	 * @param resourceSn 资源标识
    	 */
    	public void delPermission(String principalType, int principalSn,
    			int resourceSn) {
    		getHibernateTemplate()
    			.delete
    		    (
    	    		findACL(principalType, principalSn, resourceSn)
                );
    	}
    
    	/**
    	 * 这是在用户授权页面调用的方法
    	 * 设置用户某个资源授权的继承特性
    	 * 添加或更新用户的继承特性
    	 * i.	-1继承:这些权限将使用其(即用户)所拥有的角色的权限,而不使用其(即用户)单独设置的权限
    	 * ii.	0表示不继承:这些权限将使用其单独设置的权限,而不使用其所拥有的角色的权限
    	 * @param userId 用户标识 
    	 * @param sourceSn 资源标识 模块Id
    	 * @param yes true表示继承,false表示不继承
    	 */
    	public void addOrUpdateUserExtends(int userId, int sourceSn, boolean yes) {
    		
    		//根据主体标识和资源标识查找ACL实例
    		ACL acl = findACL(ACL.TYPE_USER	,userId, sourceSn);
    
    		//如果存在ACL实例,则更新其授权
    		if (yes) {
    			acl.setExtends(yes);
    			getHibernateTemplate().update(acl);
    			return;
    		}
    		
    		//如果不存在ACL实例,则创建ACL实例
    		acl = new ACL();
    		acl.setPrincipalType(ACL.TYPE_USER);
    		acl.setPrincipalSn(userId);
    		acl.setResourceSn(sourceSn);
    		acl.setExtends(yes);
    		getHibernateTemplate().save(acl);
    	}
    	
    	/**
    	 * 根据主体类型、主体标识、资源标识查找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;
    	}
    	
    	/**
    	 * 页面加载时,加载所有的授权信息
    	 * @param principalType
    	 * @param principalSn
    	 * @return
    	 */
    	public List searchACLRecord(String principalType, int principalSn) {
    		String sql = "select resourceSn,aclState&1,aclState&2,"
    				+ "aclState&4,aclState&8,aclTriState from T_ACL where "
    				+ "principalType='"+principalType+"' and principalSn="+principalSn;
    		
    		List aclRecord = getSession().createSQLQuery(sql).list();
    		return aclRecord;
    	}
    }
    


    通过DWR,在jsp页面上面调用Manager层的相应的方法,加载时实现对已授权信息的加载,以及用户对权限的动态控制。

    <%@ page language="java" contentType="text/html; charset=GB18030"
        pageEncoding="GB18030"%>
    <%@ include file="/common/common.jsp" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    	<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
    	
    	<c:choose>
    		<c:when test="${aclForm.principalType eq 'Role' }">
    			<c:set var="title" value="请给角色【${role.name }】授权" />
    		</c:when>
    		<c:otherwise>
    			<c:set var="title" value="请给用户【${user.person.name }】授权" />
    		</c:otherwise>
    	</c:choose>
    	<title>${title }</title>
    	
    	<link href="style/oa.css" rel="stylesheet" type="text/css">
    	<script language="javascript" src="script/public.js"></script>
    	<script type="text/javascript" src="dwr/engine.js"></script>
    	<script type="text/javascript" src="dwr/util.js"></script>
    	<script type="text/javascript" src="dwr/interface/aclManager.js"></script>
    	<script type="text/javascript">
    		//授权
    		function addOrUpdatePermission(field){
    			//如果被选择上,则同时选择其"不继承"和"启用"checkbox
    			if(field.checked){
    				$(field.resourceSn+"_USE").checked = true;
    				<c:if test="${aclForm.principalType eq 'User' }">
    				$(field.resourceSn+"_EXT").checked = true;
    				</c:if>
    			}
    			aclManager.addOrUpdatePermission(
    					"${aclForm.principalType}",
    					${aclForm.principalSn},
    					field.resourceSn,
    					field.permission,
    					field.checked
    			);
    		}
    		
    		//设置用户的继承特性
    		function addOrUpdateUserExtends(field){
    			aclManager.addOrUpdateUserExtends(
    				${aclForm.principalSn},
    				field.resourceSn,
    				!field.checked
    			);
    		}
    		//点击 启用  checkbox
    		function usePermission(field){
    			//如果checkbox被选中,意味着需要更新ACL的状态
    			//更新C/R/U/D以及Extends状态
    			
    			//设置为同步状态,以便DWR依次发出下列请求
    			dwr.engine.setAsync(false);
    			
    			if(field.checked){
    				//更新C状态
    				addOrUpdatePermission($(field.resourceSn+"_C"));
    				//更新R状态
    				addOrUpdatePermission($(field.resourceSn+"_R"));
    				//更新U状态
    				addOrUpdatePermission($(field.resourceSn+"_U"));
    				//更新D状态
    				addOrUpdatePermission($(field.resourceSn+"_D"));
    				//更新Extends状态
    				<c:if test="${aclForm.principalType eq 'User' }">
    					addOrUpdateUserExtends($(field.resourceSn+"_EXT"));	
    				</c:if>
    			}else{
    				//如果不启用,则删除授权信息
    				aclManager.delPermission(
    					"${aclForm.principalType}",
    					${aclForm.principalSn},
    					field.resourceSn
    				);
    				
    				//并且在界面上去掉相应的CRUD选择的选项
    				$(field.resourceSn+"_C").checked = false;
    				$(field.resourceSn+"_R").checked = false;
    				$(field.resourceSn+"_U").checked = false;
    				$(field.resourceSn+"_D").checked = false;
    				<c:if test="${aclForm.principalType eq 'User' }">
    					$(field.resourceSn+"_EXT").checked = false;	
    				</c:if>
    			}
    		}
    		
    		//打开界面时,从数据库中加载授权信息
    		function initTable(){
    			aclManager.searchACLRecord(
    				"${aclForm.principalType}",
    				${aclForm.principalSn},	
    				function(datas){
    					for(var i=0;i<datas.length;i++){
    						var resourceSn =datas[i][0];
    						var cState = datas[i][1];
    						var rState = datas[i][2];
    						var uState = datas[i][3];
    						var dState = datas[i][4];
    						var extState = datas[i][5];
    						$(resourceSn+"_C").checked =cState ==0 ? false : true;
    						$(resourceSn+"_R").checked =rState ==0 ? false : true;
    						$(resourceSn+"_U").checked =uState ==0 ? false : true;
    						$(resourceSn+"_D").checked =dState ==0 ? false : true;
    						//等于0,不继承,就要选择上,所以为true
    						<c:if test="${aclForm.principalType eq 'User' }">
    							$(resourceSn+"_EXT").checked=extState ==0 ? true : false;
    						</c:if>
    						$(resourceSn+"_USE").checked = true;
    					}
    				}
    			);
    		}
    	</script>
    </head>
    <body onload="initTable()">
    	<form action="person.do">
    		<TABLE class="tableEdit" border="0" cellspacing="1" cellpadding="0" style="580px;">
    			<TBODY>
    				<TR>
    					<td>
    						<table class="tableEdit" style="580px;" cellspacing="0" border="0" cellpadding="0">
    							<tr>
    							<!-- tdEditContent -->		
    								<td class="tdEditLabel" >顶级模块</td>			
    								<td class="tdEditContent">二级模块</td>
    								<td class="tdEditLabel">权限</td>			
    						
    								<c:if test="${aclForm.principalType eq 'User' }">
    									<td class="tdEditLabel">不继承</td>	
    								</c:if>
    								<td class="tdEditLabel">启用</td>	
    							</tr>
    							
    							<!-- 输出模块树 -->
    							<c:forEach items="${moduleList }" var="module">
    								<tr>
    									<td>${module.name }</td>
    									<td>  </td>
    									<td>
    										<input type="checkbox" id="${module.id }_C" resourceSn="${module.id }" permission="0" onclick="addOrUpdatePermission(this)">C
    										<input type="checkbox" id="${module.id }_R" resourceSn="${module.id }" permission="1" onclick="addOrUpdatePermission(this)">R
    										<input type="checkbox" id="${module.id }_U" resourceSn="${module.id }" permission="2" onclick="addOrUpdatePermission(this)">U
    										<input type="checkbox" id="${module.id }_D" resourceSn="${module.id }" permission="3" onclick="addOrUpdatePermission(this)">D
    									</td>
    									<c:if test="${aclForm.principalType eq 'User' }">
    										<td>
    											<input type="checkbox"  id="${module.id }_EXT" resourceSn="${module.id }" onclick="addOrUpdateUserExtends(this)">
    										</td>
    									</c:if>
    											<td>
    											<input type="checkbox" id="${module.id }_USE" resourceSn="${module.id }" onclick="usePermission(this)">
    											</td>
    								</tr>
    							
    							<c:forEach items="${module.children }" var="child">
    								<tr>
    									<td>  </td>
    									<td>${child.name }</td>
    									<td>
    										<input type="checkbox" id="${child.id }_C" resourceSn="${child.id }" permission="0" onclick="addOrUpdatePermission(this)">C
    										<input type="checkbox" id="${child.id }_R" resourceSn="${child.id }" permission="1" onclick="addOrUpdatePermission(this)">R
    										<input type="checkbox" id="${child.id }_U" resourceSn="${child.id }" permission="2" onclick="addOrUpdatePermission(this)">U
    										<input type="checkbox" id="${child.id }_D" resourceSn="${child.id }" permission="3" onclick="addOrUpdatePermission(this)">D
    									</td>
    									<c:if test="${aclForm.principalType eq 'User' }">
    										<td>
    											<input type="checkbox"  id="${child.id }_EXT" resourceSn="${child.id }" onclick="addOrUpdateUserExtends(this)">
    										</td>
    									</c:if>
    									<td><input type="checkbox" id="${child.id }_USE" onclick="usePermission(this)" resourceSn="${child.id }"></td>
    								</tr>
    							</c:forEach>
    							</c:forEach>
    						</table>
    					</td>
    				</TR>
    			</TBODY>
    		</TABLE>
    	</form>
    </body>
    </html>

    下面是通过点击角色授权或者用户授权,进入的授权界面:



    这个过程说难不难,说简单也不简单。我认为这个功能的主要亮点有:

    1、对多选框的动态控制;

    2、巧妙的使用位运算完成授权与认证。


  • 相关阅读:
    正则表达式
    mvc3路由设置
    MVC 过滤器
    mvc3之自定义类实现路由配置和URL的生成
    Mvc View
    定义一个底层的泛型
    一个关于字典查找引发的思考——BinarySearch
    Linq学习之旅——Linq to Objects之延期执行方法(上篇)
    Linq学习之旅——Linq to Objects之立即执行方法(下篇)
    Linq学习之旅——Linq to Objects之延期执行方法(下篇)
  • 原文地址:https://www.cnblogs.com/riskyer/p/3400468.html
Copyright © 2020-2023  润新知