B/S系統(tǒng)權(quán)限控制的一種簡(jiǎn)單方法
看了網(wǎng)上一些關(guān)于權(quán)限控制的帖子,越看越迷糊,什么用AOP(Aspect Oriented Programming,面向方面編程),用容器,RBAC(基于角色的訪問(wèn)控制方法),SSO,Jive的Proxy模式等等等等,且又是role又是group,真是頭都大了,先寫(xiě)個(gè)簡(jiǎn)單的實(shí)現(xiàn)方法,以后再研究高深的。此方法不依賴容器框架,適用于小系統(tǒng)(主要JSP頁(yè)面要少于100,因?yàn)槭怯簿幋a到JSP),適用于要精確控制頁(yè)面field的情況較多的系統(tǒng)。
(插句話:要分清權(quán)限控制與業(yè)務(wù)邏輯,業(yè)務(wù)邏輯就是情況由系統(tǒng)運(yùn)行時(shí)的某些條件決定,如學(xué)生管理系統(tǒng)中,某一學(xué)生進(jìn)入系統(tǒng),只能看自己的記錄,因?yàn)榭煽吹挠涗浭怯蓪W(xué)號(hào)來(lái)決定的,所以這是業(yè)務(wù)邏輯,而又如學(xué)生不能看老師的記錄,這是有學(xué)生的身份來(lái)決定的,所以這是權(quán)限控制。)
好了,進(jìn)入正題!
建表:
user(user信息: userID userPassword 等)
role(role描述:roleID roleDesc)
permission(permission描述:permissionID permissionDesc)
user-role(user role對(duì)應(yīng)關(guān)系表:userID roleID)
role-permission(role permission對(duì)應(yīng)關(guān)系表:roleID permissionID)
user-permission(user permission對(duì)應(yīng)關(guān)系表:userID permissionID)
重要申明:
1 此處role沒(méi)有繼承關(guān)系,只是permission的集合
2 user-permission表只是為了方便,其數(shù)據(jù)是根據(jù)user-role role-permission兩表得來(lái),只有在user-role role-permission兩表有更新的時(shí)候更新此表,并不能單獨(dú)賦予user某個(gè)permission,只能賦予user一個(gè)或多個(gè)role。
3 permission的分配,這是一個(gè)難點(diǎn),很多比較復(fù)雜的權(quán)限控制系統(tǒng)也是因?yàn)檫@個(gè)才發(fā)展出來(lái),此處把它盡量想簡(jiǎn)單,不考慮業(yè)務(wù)邏輯,以頁(yè)面為視角,分兩層,首先是需要控制的jsp頁(yè)面,然后是需要控制的頁(yè)面field(包括link,text,textbox,button等等),field這一層還有privilege之分(R和W,即可讀和可寫(xiě))
基本思路:進(jìn)入JSP頁(yè)面時(shí),檢查用戶信息,查到用戶有此permission就包含此代碼,如果沒(méi)有此permission就不包含此代碼,此功能由Tag來(lái)完成(不會(huì)寫(xiě)Tag?不要緊,抄!)。看代碼吧!
1 建表(如上)
2 建兩個(gè)class(bean) (UserProfile是用戶基本信息 UserPermission是permission )
UserProfile.java: package com.××.××.××; import java.util.Collection; public class UserProfile { private String userId; private String userType; private String companyNo; private String companyName; private String companyType; private Collection userPermissions; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserType() { return userType; } public void setUserType(String userType) { this.userType = userType; } public String getCompanyNo() { return companyNo; } public void setCompanyNo(String companyNo) { this.companyNo = companyNo; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public String getCompanyType() { return companyType; } public void setCompanyType(String companyType) { this.companyType = companyType; } public Collection getUserPermissions() { return userPermissions; } public void setUserPermissions(Collection userPermissions) { this.userPermissions = userPermissions; } } UserPermission.java: package com.××.××.××; public class UserPermission { private int permissionId; private String privilege; public int getPermissionId() { return permissionId; } public void setPermissionId(int permissionId) { this.permissionId = permissionId; } public String getPrivilege() { return privilege; } public void setPrivilege(String privilege) { this.privilege = privilege; } } 3 加兩個(gè)Tag(Page與Field): SecurityTagForPage.java: package com.**.**.taglib; import java.util.*; public class SecurityTagForPage extends TagSupport{ private int permissionID; public int doEndTag() throws JspException{ HttpSession session = pageContext.getSession(); //登陸時(shí)把該user的userProfile放到session里 UserProfile userProfile = (UserProfile)session.getAttribute("userProfile"); Collection collection= userProfile.getUserPermissions(); Iterator it = collection.iterator() ; while(it.hasNext()){ UserPermission userPermission = (UserPermission)it.next(); if ((permissionID == userPermission.getPermissionId())){ return EVAL_PAGE; } } return SKIP_PAGE; } public int getPermissionID(){ return permissionID; } public void setPermissionID(int permissionID){ this.permissionID = permissionID; } } SecurityTagForField: public class SecurityTagForField extends TagSupport{ private int permissionID; private String privilege; public int doStartTag() throws JspException{ HttpSession session = pageContext.getSession(); UserProfile userProfile = (UserProfile)session.getAttribute("userProfile"); Collection collection= userProfile.getUserPermissions(); Iterator it = collection.iterator() ; while(it.hasNext()){ UserPermission userPermission = (UserPermission)it.next(); if (privilege ==null){ if ( (permissionID == userPermission.getPermissionId())){ return EVAL_BODY_INCLUDE; } }else{ if ((permissionID == userPermission.getPermissionId()) &&(privilege.equals(userPermission.getPrivilege()))){ return EVAL_BODY_INCLUDE; } } } return SKIP_BODY; } public int getPermissionID(){ return permissionID; } public void setPermissionID(int permissionID){ this.permissionID = permissionID; } public String getPrivilege(){ return privilege; } public void setPrivilege(String privilege){ this.privilege = privilege; } }4 在web-inf目錄下建個(gè)securityTag.tld文件,內(nèi)容如下:(改一下class的目錄)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!-- a tag library descriptor -->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>security</shortname>
<uri/>
<info>access control!</info>
<tag>
<name>securityForField</name>
<tagclass>com.companyname.prjname.taglib.SecurityTagForField</tagclass>
<attribute>
<name>permissionID</name>
<required>true</required>
</attribute>
<attribute>
<name>privilege</name>
</attribute>
</tag>
<tag>
<name>securityForPage</name>
<tagclass>com.companyname.prjname.taglib.SecurityTagForPage</tagclass>
<attribute>
<name>permissionID</name>
<required>true</required>
</attribute>
</tag>
</taglib>
5 修改需要控制的jsp
在jsp頁(yè)面這樣寫(xiě):
<%@ taglib uri="/WEB-INF/securityTag.tld" prefix="security" %>
<%@ page import="com.hp.elog2.util.Util" %>
<security:securityForPage permissionID="36" />
.......
<security:securityForField permissionID="46" privilege="R">
<td><html:text name="formBean" property="property1" readonly="true" /></td>
</security:securityForField>
<security:securityForField permissionID="46" privilege="W">
<td><html:text name="formBean" property="property1" /></td>
</security:securityForField>
......
這樣就大功告成了,建議在所有jsp頁(yè)面完成后再做權(quán)限控制這一塊(添加Tag),主要都是些Copy+C和Copy+V的工作。
此方法最大的問(wèn)題就是hardcode太多,但結(jié)構(gòu)簡(jiǎn)單,思路清晰,適用范圍廣。
復(fù)雜的方法希望同道之士于我聯(lián)系leon_sandy@tom.com,共同研究!
posted on 2006-04-26 16:58 都市淘沙者 閱讀(343) 評(píng)論(0) 編輯 收藏 所屬分類: JSP/PHP