為了設計一套具有較強可擴展性的用戶(hù)認證管理,需要建立用戶(hù)、角色和權限等數據庫表,并且建立之間的關(guān)系,具體實(shí)現如下。
用戶(hù)僅僅是純粹的用戶(hù),用來(lái)記錄用戶(hù)相關(guān)信息,如用戶(hù)名、密碼等,權限是被分離出去了的。用戶(hù)(User)要擁有對某種資源的權限,必須通過(guò)角色(Role)去關(guān)聯(lián)。
用戶(hù)通常具有以下屬性:
ü 編號,在系統中唯一。
ü 名稱(chēng),在系統中唯一。
ü 用戶(hù)口令。
ü 注釋?zhuān)枋鲇脩?hù)或角色的信息。
角色是使用權限的基本單位,擁有一定數量的權限,通過(guò)角色賦予用戶(hù)權限,通常具有以下屬性:
ü 編號,在系統中唯一。
ü 名稱(chēng),在系統中唯一。
ü 注釋?zhuān)枋鼋巧畔?/font>
權限指用戶(hù)根據角色獲得對程序某些功能的操作,例如對文件的讀、寫(xiě)、修改和刪除功能,通常具有以下屬性:
ü 編號,在系統中唯一。
ü 名稱(chēng),在系統中唯一。
ü 注釋?zhuān)枋鰴嘞扌畔?/font>
一個(gè)用戶(hù)(User)可以隸屬于多個(gè)角色(Role),一個(gè)角色組也可擁有多個(gè)用戶(hù),用戶(hù)角色就是用來(lái)描述他們之間隸屬關(guān)系的對象。用戶(hù)(User)通過(guò)角色(Role)關(guān)聯(lián)所擁有對某種資源的權限,例如
l 用戶(hù)(User):
UserID UserName UserPwd
1 張三 xxxxxx
2 李四 xxxxxx
……
l 角色(Role):
RoleID RoleName RoleNote
01 系統管理員 監控系統維護管理員
02 監控人員 在線(xiàn)監控人員
03 調度人員 調度工作人員
04 一般工作人員 工作人員
……
l 用戶(hù)角色(User_Role):
UserRoleID UserID RoleID UserRoleNote
1 1 01 用戶(hù)“張三”被分配到角色“系統管理員”
2 2 02 用戶(hù)“李四”被分配到角色“監控人員”
3 2 03 用戶(hù)“李四”被分配到角色“調度人員”
……
從該關(guān)系表可以看出,用戶(hù)所擁有的特定資源可以通過(guò)用戶(hù)角色來(lái)關(guān)聯(lián)。
一個(gè)角色(Role)可以擁有多個(gè)權限(Permission),同樣一個(gè)權限可分配給多個(gè)角色。例如:
l 角色(Role):
RoleID RoleName RoleNote
01 系統管理員 監控系統維護管理員
02 監控人員 在線(xiàn)監控人員
03 調度人員 調度工作人員
04 一般工作人員 工作人員
……
l 權限(Permission):
PermissionID PermissionName PermissionNote
0001 增加監控 允許增加監控對象
0002 修改監控 允許修改監控對象
0003 刪除監控 允許刪除監控對象
0004 察看監控信息 允許察看監控對象
……
l 角色權限(Role_Permission):
RolePermissionID RoleID PermissionID RolePermissionNote
1 01 0001 角色“系統管理員”具有權限“增加監控”
2 01 0002 角色“系統管理員”具有權限“修改監控”
3 01 0003 角色“系統管理員”具有權限“刪除監控”
4 01 0004 角色“系統管理員”具有權限“察看監控”
5 02 0001 角色“監控人員”具有權限“增加監控”
6 02 0004 角色“監控人員”具有權限“察看監控”
……
由以上例子中的角色權限關(guān)系可以看出,角色權限可以建立角色和權限之間的對應關(guān)系。
用戶(hù)權限系統的核心由以下三部分構成:創(chuàng )造權限、分配權限和使用權限。
第一步由Creator創(chuàng )造權限(Permission),Creator在設計和實(shí)現系統時(shí)會(huì )劃分。利用存儲過(guò)程CreatePermissionInfo(@PermissionName,@PermissionNote)創(chuàng )建權限信息,指定系統模塊具有哪些權限。
第二步由系統管理員(Administrator)創(chuàng )建用戶(hù)和角色,并且指定用戶(hù)角色(User-Role)和角色權限(Role-Permission)的關(guān)聯(lián)關(guān)系。
1) Administrator具有創(chuàng )建用戶(hù)、修改用戶(hù)和刪除用戶(hù)的功能:
l 存儲過(guò)程CreateUserInfo(@UserName,@UserPwd)創(chuàng )建用戶(hù)信息;
l 存儲過(guò)程ModifyUserInfo(@UserName,@UserPwd)修改用戶(hù)信息;
l 存儲過(guò)程DeleteUserInfo(@UserID)刪除用戶(hù)信息;
2) Administrator具有創(chuàng )建角色和刪除角色的功能:
l 存儲過(guò)程CreateRoleInfo(@RoleName,@RoleNote)創(chuàng )建角色信息;
l 存儲過(guò)程DeleteRoleInfo(@RoleID)刪除角色信息;
3)Administrator具有建立用戶(hù)和角色、角色和權限的關(guān)聯(lián)關(guān)系功能:
l 存儲過(guò)程GrantUserRole(@UserID,@RoleID,@UserRoleNote)建立用戶(hù)和角色的關(guān)聯(lián)關(guān)系;
l 存儲過(guò)程DeleteUserRole(@UserRoleID)刪除用戶(hù)和角色的關(guān)聯(lián)關(guān)系;
l 存儲過(guò)程GrantRolePermission(@RoleID,@PermissionID,@RolePermissionNote)建立角色和權限的關(guān)聯(lián)關(guān)系;
l 存儲過(guò)程DeleteRolePermission(@RolePermissionID)刪除角色和權限的關(guān)聯(lián)關(guān)系;
第三步用戶(hù)(User)使用Administrator分配給的權限去使用各個(gè)系統模塊。利用存儲過(guò)程GetUserRole(@UserID, @UserRoleID output),GetRolePermission(@RoleID,@Role-
-PermissinID output)獲得用戶(hù)對模塊的使用權限。
當用戶(hù)通過(guò)驗證后,由系統自動(dòng)生成一個(gè)128位的TicketID保存到用戶(hù)數據庫表中,建立存儲過(guò)程Login(@UserID,@UserPwd,@TicketID output)進(jìn)行用戶(hù)認證,認證通過(guò)得到一個(gè)TicketID,否則TicketID為null。其流程圖如下:
圖1 Login流程圖
得到TicketID后,客戶(hù)端在調用服務(wù)端方法時(shí)傳遞TicketID,通過(guò)存儲過(guò)程JudgeTicketPermission(@TicketID,@PermissionID)判斷TicketID對應的用戶(hù)所具有的權限,并根據其權限進(jìn)行方法調用。
當用戶(hù)退出系統時(shí),建立存儲過(guò)程Logout(@UserID)來(lái)退出系統。當用戶(hù)異常退出系統時(shí),根據最后的登陸時(shí)間(LastSignTime)確定用戶(hù)的TickeID,建立存儲過(guò)程ExceptionLogout(@UserID,@LastSignTime)處理用戶(hù)的異常退出。
圖2 Logout流程圖
WebService可以采用SoapHeader中寫(xiě)入TicketID來(lái)使得TicketID從客戶(hù)端傳遞給服務(wù)端。.Net Remoting可以采用CallContext類(lèi)來(lái)實(shí)現TicketID從客戶(hù)端傳遞給服務(wù)端。
圖3 數據庫關(guān)系圖
Static_User
| Static_User字段名
| 詳細解釋
| 類(lèi)型
| 備注
|
| UserID
| 路線(xiàn)編號
| varchar(20)
| PK
|
| UserName
| 用戶(hù)名稱(chēng)
| varchar(20)
|
|
| UserPwd
| 用戶(hù)密碼
| varchar(20)
|
|
| LastSignTime
| 最后登陸時(shí)間
| datatime
|
|
| SignState
| 用戶(hù)登陸狀態(tài)標記
| int
|
|
| TickeID
| 驗證票記錄編號
| varchar(128)
|
|
|
|
|
|
|
Static_Role
| Static_User字段名
| 詳細解釋
| 類(lèi)型
| 備注
|
| RoleID
| 角色編號
| varchar(20)
| PK
|
| RoleName
| 角色名稱(chēng)
| varchar(20)
|
|
| RoleNote
| 角色信息描述
| varchar(20)
|
|
|
|
|
|
|
Static_User_Role
| Static_User字段名
| 詳細解釋
| 類(lèi)型
| 備注
|
| UserRoleID
| 用戶(hù)角色編號
| varchar(20)
| PK
|
| UserID
| 用戶(hù)編號
| varchar(20)
| FK
|
| RoleID
| 角色編號
| varchar(20)
| FK
|
| UserRoleNote
| 用戶(hù)角色信息描述
| varchar(20)
|
|
|
|
|
|
|
Static_Permission
| Static_User字段名
| 詳細解釋
| 類(lèi)型
| 備注
|
| PermissionID
| 編號
| varchar(20)
| PK
|
| PermissionName
| 權限名稱(chēng)
| varchar(20)
|
|
| PermissionNote
| 全息信息描述
| varchar(20)
|
|
|
|
|
|
|
Static_Role_Permission
| Static_User字段名
| 詳細解釋
| 類(lèi)型
| 備注
|
| RolePermissionID
| 角色權限編號
| varchar(20)
| PK
|
| RoleID
| 角色編號
| varchar(20)
| FK
|
| PermissionID
| 權限編號
| varchar(20)
| FK
|
| RolePermissionNote
| 角色權限信息描述
| varchar(20)
|
|
|
|
|
|
|
對 SQL 數據庫執行自定義身份驗證和授權。在這種情況中,應向服務(wù)傳遞自定義憑據(如用戶(hù)名和密碼),并讓服務(wù)自己處理身份驗證和授權。 將額外的信息連同請求一起傳遞給 XML Web 服務(wù)的簡(jiǎn)便方法是通過(guò) SOAP 標頭。為此,需要在服務(wù)中定義一個(gè)從 SOAPHeader 派生的類(lèi),然后將服務(wù)的公共字段聲明為該類(lèi)型。這在服務(wù)的公共合同中公開(kāi),并且當從 WebServiceUtil.exe 創(chuàng )建代理時(shí)可由客戶(hù)端使用,如下例所示:
using System.Web.Services;
using System.Web.Services.Protocols;
// AuthHeader class extends from SoapHeader
public class AuthHeader : SoapHeader {
public string Username;
public string Password;
}
public class HeaderService : WebService {
public AuthHeader sHeader;
...
}
服務(wù)中的每個(gè) WebMethod 都可以使用 SoapHeader 自定義屬性定義一組關(guān)聯(lián)的標頭。默認情況下,標頭是必需的,但也可以定義可選標頭。SoapHeader 屬性指定公共字段的名稱(chēng)或者 Client 或 Server 類(lèi)的屬性(本標題中稱(chēng)為 Headers 屬性)。在為輸入標頭調用方法前,WebService 設置 Headers 屬性的值;而當方法為輸出標頭返回時(shí),WebService 檢索該值。
[WebMethod(Description="This method requires a custom soap header set by the caller")]
[SoapHeader("sHeader")]
public string SecureMethod() {
if (sHeader == null)
return "ERROR: Please supply credentials";
else
return "USER: " + sHeader.Username;
}
然后,客戶(hù)端在調用要求標頭的方法之前,直接在代理類(lèi)上設置標頭,如下面的示例所示:
HeaderService h = new HeaderService();
AuthHeader myHeader = new AuthHeader();
myHeader.Username = "username";
myHeader.Password = "password";
h.AuthHeader = myHeader;
String result = h.SecureMethod();
CallContext提供與執行代碼路徑一起傳送的屬性集,CallContext是類(lèi)似于方法調用的線(xiàn)程本地存儲的專(zhuān)用集合對象,并提供對每個(gè)邏輯執行線(xiàn)程都唯一的數據槽。數據槽不在其他邏輯線(xiàn)程上的調用上下文之間共享。當 CallContext 沿執行代碼路徑往返傳播并且由該路徑中的各個(gè)對象檢查時(shí),可將對象添加到其中。當對另一個(gè) AppDomain 中的對象進(jìn)行遠程方法調用時(shí),CallContext 類(lèi)將生成一個(gè)與該遠程調用一起傳播的 LogicalCallContext 實(shí)例。只有公開(kāi) ILogicalThreadAffinative 接口并存儲在 CallContext 中的對象被在 LogicalCallContext 中傳播到 AppDomain 外部。不支持此接口的對象不在 LogicalCallContext 實(shí)例中與遠程方法調用一起傳輸。
CallContext.SetData方法存儲給定對象并將其與指定名稱(chēng)關(guān)聯(lián),CallContext.GetData方法從 CallContext 中檢索具有指定名稱(chēng)的對象。
下面的代碼示例說(shuō)明如何使用 SetData 方法將主體和標識對象傳輸到遠程位置以進(jìn)行標識。
public class ClientClass {
public static void
GenericIdentity ident = new GenericIdentity("Bob");
GenericPrincipal prpal = new GenericPrincipal(ident,
Newstring[] {"Level1"});
LogicalCallContextData data =
new LogicalCallContextData(prpal);
//Enter data into the CallContext
CallContext.SetData("test data", data);
Console.WriteLine(data.numOfAccesses);
ChannelServices.RegisterChannel(new TcpChannel());
RemotingConfiguration.RegisterActivatedClientType(
typeof(HelloServiceClass), "tcp://localhost:8082");
HelloServiceClass service = new HelloServiceClass();
if(service == null) {
Console.WriteLine("Could not locate server.");
return;
}
// call remote method
Console.WriteLine();
Console.WriteLine("Calling remote object");
Console.WriteLine(service.HelloMethod("Caveman"));
Console.WriteLine(service.HelloMethod("Spaceman"));
Console.WriteLine(service.HelloMethod("Bob"));
Console.WriteLine("Finished remote object call");
Console.WriteLine();
//Extract the returned data from the call context
LogicalCallContextData returnedData =
(LogicalCallContextData)CallContext.GetData("test data");
Console.WriteLine(data.numOfAccesses);
Console.WriteLine(returnedData.numOfAccesses);
}
}
下面的代碼示例說(shuō)明如何使用 GetData 方法將主體和標識對象傳輸到遠程位置以進(jìn)行標識。
using System;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Security.Principal;
public class HelloServiceClass : MarshalByRefObject {
static int n_instances;
int instanceNum;
public HelloServiceClass() {
n_instances++;
instanceNum = n_instances;
Console.WriteLine(this.GetType().Name + " has been created.
Instance # = {0}", instanceNum);
}
~HelloServiceClass() {
Console.WriteLine("Destroyed instance {0} of
HelloServiceClass.", instanceNum);
}
public String HelloMethod(String name) {
//Extract the call context data
LogicalCallContextData data =
(LogicalCallContextData)CallContext.GetData("test data");
IPrincipal myPrincipal = data.Principal;
//Check the user identity
if(myPrincipal.Identity.Name == "Bob") {
Console.WriteLine("\nHello {0}, you are identified!",
myPrincipal.Identity.Name);
Console.WriteLine(data.numOfAccesses);
}
else {
Console.WriteLine("Go away! You are not identified!");
return String.Empty;
}
// calculate and return result to client
return "Hi there " + name + ".";
}
}
WebService端代碼主要進(jìn)行對數據庫的操作,建立起Client操作數據庫所需要的方法,供Client的端調用。
1)class UserInfoMng() 用戶(hù)信息管理類(lèi),其中包括方法:
l CreateUserInfo(string UserName string UserPwd) 建立用戶(hù)信息,調用存儲過(guò)程CreateUserInfo(@UserName,@UserPwd)
l ModifyUserInfo(string UserName string UserPwd) 修改用戶(hù)信息,調用存儲過(guò)程ModifyUserInfo(@UserName,@UserPwd)
l DeleteUserInfo() 刪除用戶(hù)信息,調用存儲過(guò)程DeleteUserInfo
(@UserID)
2)class UserAuthentication() 用戶(hù)認證類(lèi),用來(lái)實(shí)現用戶(hù)角色、權限的設置,包括方法:
l CreatePermissionInfo(string PermissionName string Permissi-
-onNote) 建立權限信息,調用存儲過(guò)程CreatePermissionInfo
(@PermissionName,@PermissionNote)
l CreateRoleInfo(string RoleName string RoleNote) 建立角色信息,調用存儲過(guò)程CreateRoleInfo(@RoleName,@RoleNote)
l DeleteRoleInfo() 刪除角色信息,調用存儲過(guò)程DeleteRoleInfo
(@RoleID)
l GrantUserRole(string UserID string RoleID string UserRoleNote) 授予用戶(hù)角色,調用存儲過(guò)程GrantUserRole(@UserID,@RoleID,
@UserRoleNote)
l DeleteUserRole() 刪除用戶(hù)角色,調用存儲過(guò)程DeleteUserRole
(@UserRoleID)
l GrantRolePermission(string RoleID string PermissionID string RolePermissionNote) 授予角色權限,調用存儲過(guò)程GrantRolePermission(@RoleID,@PermissionID,@RolePermissionNote)
l DeleteRolePermission() 刪除授予的角色權限,調用存儲過(guò)程
DeleteRolePermission(@RolePermissionID)
Client端調用WebService方法來(lái)進(jìn)行數據庫訪(fǎng)問(wèn),Client端代碼設計主要實(shí)現界面的功能,包括:權限設置、用戶(hù)管理、用戶(hù)授權管理和用戶(hù)認證管理
1)權限設置
class PermissionInfoMng() 用戶(hù)權限信息管理類(lèi),包括方法:
l CreatePermissionInfo() 建立權限信息
2)用戶(hù)管理
class UserInfoMng() 用戶(hù)信息管理類(lèi),包括方法:
l CreateUserInfo() 建立用戶(hù)信息
l ModifyUserInfo() 修改用戶(hù)信息
l DeleteUserInfo() 刪除用戶(hù)信息
3)用戶(hù)授權管理
class RoleInfoMng() 角色信息管理類(lèi),包括方法:
l CreateRoleInfo() 建立角色信息
l DeleteRoleInfo() 刪除角色信息
class UserRoleMng() 用戶(hù)角色管理類(lèi),包括方法:
l GrantUserRole() 授予用戶(hù)角色
l DeleteUserRole() 刪除用戶(hù)角色
class RolePermissionMng() 角色權限管理類(lèi),包括方法
l GrantRolePermission() 授予角色權限
l DeleteRolePermission() 刪除角色權限
4)用戶(hù)認證管理
class Authentication() 用戶(hù)認證類(lèi),包括方法:
l Login(string UserName string UserPwd) 用戶(hù)登陸認證,用戶(hù)認證通過(guò)分配給用戶(hù)一個(gè)TicketID,否則TicketID則為null
l Logout() 用戶(hù)正常退出
l ExceptionLogout() 用戶(hù)異常退出
聯(lián)系客服