天天看點

使用者認證管理設計方案(轉)

1 設計思路

為了設計一套具有較強可擴充性的使用者認證管理,需要建立使用者、角色和權限等資料庫表,并且建立之間的關系,具體實作如下。

使用者僅僅是純粹的使用者,用來記錄使用者相關資訊,如使用者名、密碼等,權限是被分離出去了的。使用者(user)要擁有對某種資源的權限,必須通過角色(role)去關聯。

使用者通常具有以下屬性:

ü         編号,在系統中唯一。

ü         名稱,在系統中唯一。

ü         使用者密碼。

ü         注釋,描述使用者或角色的資訊。

角色是使用權限的基本機關,擁有一定數量的權限,通過角色賦予使用者權限,通常具有以下屬性:

ü         注釋,描述角色資訊

       權限指使用者根據角色獲得對程式某些功能的操作,例如對檔案的讀、寫、修改和删除功能,通常具有以下屬性:

ü         注釋,描述權限資訊

一個使用者(user)可以隸屬于多個角色(role),一個角色組也可擁有多個使用者,使用者角色就是用來描述他們之間隸屬關系的對象。使用者(user)通過角色(role)關聯所擁有對某種資源的權限,例如

l         使用者(user):

userid      username      userpwd

1                   張三                 xxxxxx

2                   李四                 xxxxxx    

……

l         角色(role):

roleid           rolename          rolenote

       01                  系統管理者       監控系統維護管理者

       02                  監控人員          線上監控人員

       03                  排程人員          排程從業人員

       04                  一般從業人員   從業人員

       ……

l         使用者角色(user_role):

userroleid           userid           roleid           userrolenote

1                       1                   01                  使用者“張三”被配置設定到角色“系統管理者”

2                        2                   02                  使用者“李四”被配置設定到角色“監控人員”

3                        2                   03                  使用者“李四”被配置設定到角色“排程人員”

       從該關系表可以看出,使用者所擁有的特定資源可以通過使用者角色來關聯。

一個角色(role)可以擁有多個權限(permission),同樣一個權限可配置設定給多個角色。例如:

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        角色“監控人員”具有權限“察看監控”

       由以上例子中的角色權限關系可以看出,角色權限可以建立角色和權限之間的對應關系。

使用者權限系統的核心由以下三部分構成:創造權限、配置設定權限和使用權限。

第一步由creator創造權限(permission),creator在設計和實作系統時會劃分。利用存儲過程createpermissioninfo(@permissionname,@permissionnote)建立權限資訊,指定系統子產品具有哪些權限。

第二步由系統管理者(administrator)建立使用者和角色,并且指定使用者角色(user-role)和角色權限(role-permission)的關聯關系。

1)        administrator具有建立使用者、修改使用者和删除使用者的功能:

l         存儲過程createuserinfo(@username,@userpwd)建立使用者資訊;

l         存儲過程modifyuserinfo(@username,@userpwd)修改使用者資訊;

l         存儲過程deleteuserinfo(@userid)删除使用者資訊;

2)        administrator具有建立角色和删除角色的功能:

l         存儲過程createroleinfo(@rolename,@rolenote)建立角色資訊;

l         存儲過程deleteroleinfo(@roleid)删除角色資訊;

3)administrator具有建立使用者和角色、角色和權限的關聯關系功能:

l         存儲過程grantuserrole(@userid,@roleid,@userrolenote)建立使用者和角色的關聯關系;

l         存儲過程deleteuserrole(@userroleid)删除使用者和角色的關聯關系;

l         存儲過程grantrolepermission(@roleid,@permissionid,@rolepermissionnote)建立角色和權限的關聯關系;

l         存儲過程deleterolepermission(@rolepermissionid)删除角色和權限的關聯關系;

第三步使用者(user)使用administrator配置設定給的權限去使用各個系統子產品。利用存儲過程getuserrole(@userid, @userroleid output),getrolepermission(@roleid,@role-

-permissinid output)獲得使用者對子產品的使用權限。

當使用者通過驗證後,由系統自動生成一個128位的ticketid儲存到使用者資料庫表中,建立存儲過程login(@userid,@userpwd,@ticketid output)進行使用者認證,認證通過得到一個ticketid,否則ticketid為null。其流程圖如下:

圖1 login流程圖

得到ticketid後,用戶端在調用服務端方法時傳遞ticketid,通過存儲過程judgeticketpermission(@ticketid,@permissionid)判斷ticketid對應的使用者所具有的權限,并根據其權限進行方法調用。

當使用者退出系統時,建立存儲過程logout(@userid)來退出系統。當使用者異常退出系統時,根據最後的登陸時間(lastsigntime)确定使用者的tickeid,建立存儲過程exceptionlogout(@userid,@lastsigntime)處理使用者的異常退出。

圖2 logout流程圖

webservice可以采用soapheader中寫入ticketid來使得ticketid從用戶端傳遞給服務端。.net remoting可以采用callcontext類來實作ticketid從用戶端傳遞給服務端。

2 資料庫設計

圖3 資料庫關系圖

static_user

static_user字段名

詳細解釋

類型

備注

userid

路線編号

varchar(20)

pk

username

使用者名稱

userpwd

使用者密碼

lastsigntime

最後登陸時間

datatime

signstate

使用者登陸狀态标記

int

tickeid

驗證票記錄編号

varchar(128)

static_role

roleid

角色編号

rolename

角色名稱

rolenote

角色資訊描述

static_user_role

userroleid

使用者角色編号

使用者編号

fk

userrolenote

使用者角色資訊描述

static_permission

permissionid

編号

permissionname

權限名稱

permissionnote

全息資訊描述

static_role_permission

rolepermissionid

角色權限編号

權限編号

rolepermissionnote

角色權限資訊描述

3 .net技術概要

對 sql 資料庫執行自定義身份驗證和授權。在這種情況中,應向服務傳遞自定義憑據(如使用者名和密碼),并讓服務自己處理身份驗證和授權。 将額外的資訊連同請求一起傳遞給 xml web 服務的簡便方法是通過 soap 标頭。為此,需要在服務中定義一個從 soapheader 派生的類,然後将服務的公共字段聲明為該類型。這在服務的公共合同中公開,并且當從 webserviceutil.exe 建立代理時可由用戶端使用,如下例所示:

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;

    ...

服務中的每個 webmethod 都可以使用 soapheader 自定義屬性定義一組關聯的标頭。預設情況下,标頭是必需的,但也可以定義可選标頭。soapheader 屬性指定公共字段的名稱或者 client 或 server 類的屬性(本标題中稱為 headers 屬性)。在為輸入标頭調用方法前,webservice 設定 headers 屬性的值;而當方法為輸出标頭傳回時,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;

然後,用戶端在調用要求标頭的方法之前,直接在代理類上設定标頭,如下面的示例所示:

headerservice h = new headerservice();

authheader myheader = new authheader();

myheader.username = "username";

myheader.password = "password";

h.authheader = myheader;

string result = h.securemethod();

callcontext提供與執行代碼路徑一起傳送的屬性集,callcontext是類似于方法調用的線程本地存儲的專用集合對象,并提供對每個邏輯執行線程都唯一的資料槽。資料槽不在其他邏輯線程上的調用上下文之間共享。當 callcontext 沿執行代碼路徑往返傳播并且由該路徑中的各個對象檢查時,可将對象添加到其中。當對另一個 appdomain 中的對象進行遠端方法調用時,callcontext 類将生成一個與該遠端調用一起傳播的 logicalcallcontext 執行個體。隻有公開 ilogicalthreadaffinative 接口并存儲在 callcontext 中的對象被在 logicalcallcontext 中傳播到 appdomain 外部。不支援此接口的對象不在 logicalcallcontext 執行個體中與遠端方法調用一起傳輸。

callcontext.setdata方法存儲給定對象并将其與指定名稱關聯,callcontext.getdata方法從 callcontext 中檢索具有指定名稱的對象。

下面的代碼示例說明如何使用 setdata 方法将主體和辨別對象傳輸到遠端位置以進行辨別。

public class clientclass {

   public static void main() {

      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");

      //extract the returned data from the call context

      logicalcallcontextdata returneddata =

         (logicalcallcontextdata)callcontext.getdata("test data");

      console.writeline(returneddata.numofaccesses);

   }

下面的代碼示例說明如何使用 getdata 方法将主體和辨別對象傳輸到遠端位置以進行辨別。

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)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 + ".";

4 詳細代碼設計

webservice端代碼主要進行對資料庫的操作,建立起client操作資料庫所需要的方法,供client的端調用。

1)class userinfomng() 使用者資訊管理類,其中包括方法:

l         createuserinfo(string username string userpwd) 建立使用者資訊,調用存儲過程createuserinfo(@username,@userpwd)

l         modifyuserinfo(string username string userpwd) 修改使用者資訊,調用存儲過程modifyuserinfo(@username,@userpwd)

l         deleteuserinfo() 删除使用者資訊,調用存儲過程deleteuserinfo

(@userid)

2)class userauthentication() 使用者認證類,用來實作使用者角色、權限的設定,包括方法:

l         createpermissioninfo(string permissionname string permissi-

-onnote) 建立權限資訊,調用存儲過程createpermissioninfo

(@permissionname,@permissionnote)

l         createroleinfo(string rolename string rolenote) 建立角色資訊,調用存儲過程createroleinfo(@rolename,@rolenote)

l         deleteroleinfo() 删除角色資訊,調用存儲過程deleteroleinfo

(@roleid)

l         grantuserrole(string userid string roleid string userrolenote) 授予使用者角色,調用存儲過程grantuserrole(@userid,@roleid,

@userrolenote)

l         deleteuserrole() 删除使用者角色,調用存儲過程deleteuserrole

(@userroleid)

l         grantrolepermission(string roleid string permissionid string rolepermissionnote) 授予角色權限,調用存儲過程grantrolepermission(@roleid,@permissionid,@rolepermissionnote)

l         deleterolepermission() 删除授予的角色權限,調用存儲過程

deleterolepermission(@rolepermissionid)

client端調用webservice方法來進行資料庫通路,client端代碼設計主要實作界面的功能,包括:權限設定、使用者管理、使用者授權管理和使用者認證管理

1)權限設定

class permissioninfomng() 使用者權限資訊管理類,包括方法:

l         createpermissioninfo() 建立權限資訊

2)使用者管理

class userinfomng() 使用者資訊管理類,包括方法:

l         createuserinfo() 建立使用者資訊

l         modifyuserinfo() 修改使用者資訊

l         deleteuserinfo() 删除使用者資訊

3)使用者授權管理

class roleinfomng() 角色資訊管理類,包括方法:

l         createroleinfo() 建立角色資訊

l         deleteroleinfo() 删除角色資訊

class userrolemng() 使用者角色管理類,包括方法:

l         grantuserrole() 授予使用者角色

l         deleteuserrole() 删除使用者角色

class rolepermissionmng() 角色權限管理類,包括方法

l         grantrolepermission() 授予角色權限

l         deleterolepermission() 删除角色權限

4)使用者認證管理

class authentication() 使用者認證類,包括方法:

l         login(string username string userpwd) 使用者登陸認證,使用者認證通過配置設定給使用者一個ticketid,否則ticketid則為null

l         logout() 使用者正常退出

l         exceptionlogout() 使用者異常退出