目 錄
 
 
 
 
一 引言……………………………………………………………………………………1
二 需求分析
 (一)系統的功能要求………………………………………………………………2
 (二)系統的性能要求………………………………………………………………2
 (三)運行環境要求…………………………………………………………………2
(四)開發工具簡介…………………………………………………………………2
三 總體設計
(一)系統模塊化分…………………………………………………………………2
(二)設計思想及結構層次圖………………………………………………………3
四 數據庫設計
 (一) 數據庫模型圖…………………………………………………………………5
(二) 數據表設計……………………………………………………………………5
 (三) 視圖……………………………………………………………………………7
五 數據訪問層的詳細設計………………………………………………………………7
六 總結……………………………………………………………………………………9
七 致謝…………………………………………………………………………………10
主要參考文獻…………………………………………………………………………10
附錄………………………………………………………………………………………10
 
 
 
 
 
統一身份認證子系統數據庫設計與數據訪問層實現
 
 石 春 麗 
西南師范大學計算機與信息科學學院 重慶 400715
 
摘要:統一身份認證子系統(uia子系統)統一管理用戶和校園內各個分應用系統(成員站點)。每個注冊的校園網用戶擁有統一的網絡賬戶(用戶名/密碼),用戶通過同一個用戶名/密碼,可以訪問校園內的所有校網絡應用系統(成員站點),為用戶應用提供統一身份認證和單點登錄服務。該論文主要內容包括該系統需求分析、總體設計、數據庫的設計和數據訪問層的詳細設計與實現。
關鍵詞:用戶,成員站點,用戶角色
 
abstract: unique identity authentication subsystem (uia ) manages users and each branch application system(member site ) in campus in unison. each registered campus network user has unified network accounts (user name / the password), users can visit the schools network application system(member site) in the campus by the same user name / the password, apply to users’ application the services that unify identity authentication and some single log-in. this thesis main contents include system demand analyse , overall design ,database design and detailed design and realization of data access layer. 
 
一、引言
對于校園內部的各個應用系統,用戶使用時必須在每個系統中都注冊,登錄,比較麻煩,同時 也容易造成混亂,更帶來數據資源的重復存儲。因此需要一個專門的系統對用戶進行統一管理,即用戶只需要注冊登錄一次就可以使用各不同應用系統。當然對于各個不同的應用系統,為了用戶的使用方便,也對其進行一個邏輯上的統一管理。因此開發uia(統一身份認證)系統是很有必要的。當應用系統注冊到在uia后,我們稱之為成員站點。
對用戶的統一管理,一方面用在訪問各個成員站點時無需多次注冊登錄,既給用戶的使用帶來方便,也為成員站點節約資源,避免各個成員站點分散管理統一用戶帶來的數據冗余。另一方面也給新的成員站點(新的應用系統)的開發提供方便。
對成員站點進行統一管理,一方面給用戶的操作帶來方便,即用戶登錄uia子系統后就可以直接通過鏈接對各成員站點進行訪問。另一方面對于成員站點只需要在該系統中注冊時給出不同用戶的角色類型,便可對各類用戶進行權限控制,由該系統完成對用戶的權限分配。因此開發uia子系統(統一身份認證子系統),由小組討論完成需求分析和總體設計(模塊劃分)中部分工作,由我負責數據庫設計和數據訪問層的代碼編寫工作。
二 、需求分析
(一)系統功能要求
uia子系統要實現兩大功能,一是對用戶和系統的身份認證,二是對用戶與成員站點之間的權限控制。通過用戶的身份和成員站點對用戶的權限分配用戶可在該系統中獲得訪問某成員站點的權限,通過系統的身份和用戶對成員站點的權限控制,成員站點可在該系統中獲得察看用戶信息的權限。
(二)系統性能要求
uia子系統將會管理海量的用戶和成員站點信息,這對uia子系統的性能要求很高,同時多網絡的性能要求也很高,所以要求uia子系統首先要有容量很大的存儲設備,同時要求有較大的帶寬,保證大量用戶在訪問時不會發生網絡阻塞。
(三)運行環境要求
.net平臺,sqlserver數據庫,iis服務器
(四)開發工具簡介
microsoft sql sever是高性能客戶/服務器關系數據庫管理系統。有許多重要的新特性,如透明分布式處理、簡明管理、基于對象嵌入與鏈接技術(0le)的程序設計接口,以及與internet的集成等,選擇microsoft sql sever最重要的原因是它的可擴展性和較高的安全性。因為microsoft sql sever是基于多線程序并行數據庫內核,它能夠發揮附加處理器的優勢,在許多情況下,只有使用特定的并行數據庫和操作系統才能獲得對對稱多處理技術的支持;當然它還具備很高的安全性,對用戶資料進行有效的保護。
三 、總體設計
(一)uia子系統模塊劃分
統一身份認證子系統(uia)主要有兩大功能模塊:身份認證模塊和權限管理模塊。
身份認證模塊管理用戶身份和成員站點身份。向用戶提供在線注冊功能,用戶注冊時提供必須信息(如用戶名、密碼)該信息即為用戶身份的唯一證據,擁有該信息的用戶即為uia子系統的合法用戶;身份認證模塊還向成員站點提供在線注冊功能,成員站點注冊時需提供一些關于成員站點的基本信息,還包括為用戶定義的角色種類(如普通用戶、高級用戶、管理員用戶)。
權限管理模塊主要有:成員站點對用戶的權限控制、用戶對成員站點的權限控制、成員站點對成員站點的權限控制。用戶向某成員站點申請分配權限時,需向該成員站點提供他的某些信息,這些信息就是用戶提供給成員站點的權限,而成員站點通過uia身份認證后就可以查詢用戶信息,并給該用戶分配權限,獲得權限的用戶通過uia身份認證后就可以以某種身份訪問該成員站點。成員站點對成員站點的權限控制主要是成員站點控制向其它成員站點提供的調用接口。
uia還包括系統維護模塊和使用幫助模塊,系統維護模塊主要功能是成員站點的管理和對系統數據的維護。
uia還提供一套sdk,供各成員站點開發時使用。如用戶訪問某成員站點時,uia提供返回用戶權限的函數,供成員站點調用。
(二)設計思想及結構層次圖
1.系統總體設計思想描述如下:
用戶可以進行單點登錄,也就是用戶通過uia子系統的身份認證后,就可以訪問uia子系統的所有的該用戶擁有權限的成員站點,用戶在訪問完一個站點后,不需要再次通過認證就可以訪問他擁有權限的站點,同時向成員站點返回他相應的訪問權限;集中式授權控制是用戶向成員站點申請授權,用戶在向站點申請權限時,提供想讓站點看到的信息,即向成員站點申請授權;成員站點也向用戶授權,用戶向站點申請權限后,站點就可以為該用戶開通,用戶就獲得了在該站點的權限;還為成員站點提供管理功能,包括管理其基本信息和其成員用戶的權限,包括為用戶開通權限,禁用用戶的權限。
2.整個系統結構層次關系描述圖:
主要說明了在開發時所用的開發模式:.net層次化開發,也就是microsoft推薦的開發方式。主體部分主要有三個層:商務邏輯層、商務外觀層、數據庫訪問層。其中商務外觀層主要定義一些基本的操作,可以調用商務邏輯層,也可以調用數據庫訪問層和model層,商務邏輯層主要是定義一些操作的規則,可以調用數據庫訪問層和model層,數據庫訪問層主要是具體的對數據庫的操作,可以調用model層,通過這種層層調用來實現系統的主體功能;webservice層可以調用商務邏輯層,數據庫訪問層和model層,webui主要是提供給用戶的界面,體現系統的實際功能,可以訪問商務外觀層和model層,model層主要功能是實現層間的數據傳遞,可以被其他層調用。采用這種開發方式主要是有利于系統的維護和今后的系統擴展,如果某一層出現問題或需要更新某一層的功能,只需要修改相應的那一層,不需要修改其他層,這樣就可以問題局部化,便于解決問題。 
四、數據庫設計
uia是一個動態的信息管理系統必須是在internet/intranet技術的基礎上,基于web方式而建立客戶端與服務器端的聯系,我們構建這個數據庫的目的一方面有效安全的保存用戶的注冊信息,同時方便成員站點對用戶的權限控制和信息的查詢,因此該數據庫系統應該具有較高的安全性,另外為方便新的成員站點的加入,該系統也必須有對外開放功能的數據庫。為此,我們考慮選用microsoft sql sever 2000作為數據庫管理系統,創建一個易于實現數據共享,集業務處理、數據分析、數據查詢于一體并能保障數據高效安全的數據庫系統,根據實際的需要,數據庫內容主要分為兩大部分,一是的成語站點的基本信息,包括站點地址,站點名,站點是否開通等的信息數據,二是用戶的各種信息數據,故數據庫應包含四個必不可少的表單:
(一)數據庫模型圖:
(二)數據表的設計
1.成員站點信息表(tsites):
該數據表用來存儲成員站點的基本信息。
其中usid字段由系統自動生成,系統統一標志符表示,siteid即成員站點號是該數據表的關鍵字段,由它唯一標志成員站點,對它規定用4位整形表示;url表示成員站點的網址,sitename表示站點的網名,二者都用可變長字符串表示,但不能超過50個字符;;siteenable標志位,標志當前該站點是否開通,是否可以訪問,用一位字符表示,當取值為“1”,表示站點開通,反之未開通;
2.用戶信息表(tusers):
該數據表存儲用戶的基本信息,也是用戶注冊時需要填寫的信息。
其中uuid字段是系統自動生成的,userid表示用戶號,是關鍵字段,由它來區別不同的用戶;nikename表示用戶昵稱,用可變長字符串來表示,但長度不能超過50;email表示用戶郵箱,password用戶密碼,二者用50個以內的可變長字符串表示;userenable標志位,標志該用戶是否開通,即注冊信息是否生效,用一位字符表示,取值“1”是為真即開通,反之為假即未開通;另外為了防止用戶登錄時密碼遺忘,設置密碼提示,用提問的方式幫助用戶找回密碼,question是用戶注冊時填寫的密碼提示問題,answer是密碼提示答案,二者均用可變長字符串表示,要求長度在100之內。
3.用戶在某成員站點中的角色(tuserroles):
該表存儲不同成員站點用分配的角色類 型。
其中roleid表示角色號,是該數據表的關鍵字段,它唯一標志某個角色,規定用4位整形表示,siteid表示成員站點號,rolename表示角色名稱,用50位以內的可變長字符串表示,canadminsite標志該角色是否具有對siteid字段標志的成員站點的管理權,如果為“1”表示該角色具備此權限,如果為“0”則不具備,一般來講,對一個成員站點,只有一種角色的該字段取值為“1”,其他均為“0”。
4.成員站點對用戶分配的角色類型(troles):
roleid表示角色號,userid表示用戶號是該數據表的關鍵字段,均用4位整形表示,由二者來唯一確定某個用戶的某種角色。roleenabled表示用戶角色是否開通,用一位數據表示,取值為“1”,表示用戶角色開通,即該用戶當前可以訪問某成員站點,反之則沒有開通。
(二)系統中所用到的視圖:
vsites: 該視圖的創建主要為了方便查詢成員站點中的用戶角色。
vusers: 該視圖的創建主要為了方便查詢用戶的信息,包括用戶在各個成員站點中的角色。
五、數據訪問層的詳細設計:
根據系統功能需求和數據庫的設計可得出對數據庫的訪問主要包括四大部分:1,對成員站點信息表(tsites)的訪問;2,對用戶信息表(tusers)的訪問;3,對用戶在某成員站點中的角色(tuserroles)的訪問;4,對成員站點對用戶分配的權限(角色)類型(troles)的訪問;因此我們分別用下面四個類來實現:
(1)public class sites
該類包含以下函數:
public int createsite(sitedata site)在數據庫中添加一個新的成員站點信息。其參數是一個sitedata類型數據,sitedata是由model層定義的數據類型,從數據庫中獲取的信息是sqldatareader類型,需要將其轉換成model層中的sitedata類型便于層間數據的傳遞。
public int updatesite(sitedata site) 修改數據庫中某個成員站點信息
public int removesite(system.guid usid) 刪除數據庫中某個用戶,其參數為成員站點注冊時數據表中系統自動生成的編號usid
public sitedata getsite(system.guid usid)根據成員站點注冊時系統自動分配的編號usid來查詢該成員站點的所有信息,返回類型為model層中的sitedata類型。
public ilist listsites()查詢并列出所有成員站點信息,用鏈表ilist返回,ilist中的每一項的數據類型sitedata
(2)public class users
該類包含以下函數:
public int createuser(userdata user)在數據庫中添加一個新用戶,參數為userdata類型,其含義與sitedata相同。
public int updateuser(userdata user)修改數據庫中某個用戶信息。
public int removeuser(string nickname)刪除數據庫中某個用戶,其參數為用戶信息中的nickname 
public userdata getuser(string nickname)根據nickname查詢用戶所有信息,返回類型為model層中的userdata類型。
public ilist listusers()查詢所有用戶信息返回鏈表ilist,ilist中的每一項的數據類型userdata
(3) public class userroles
該類包含以下函數:
private int getroleid(string role,int siteid)獲取角色號,其參數為某個成員站點的siteid以及某個角色名。
public int adduserrole(userroledata userrole)添加用戶角色
public int removeuserrole(userroledata userrole)刪除一個用戶角色
public userroledata getuserrole(int userid,int siteid)獲取用戶在某個成員站點中的角色
public ilist listallusersinsite(system.guid usid)查詢所有成員站點
(4) public class userrolerules
該類包含以下函數:
public bool requestrole(string nickname,string role,system.guid usid)申請用戶角色
public bool enableuserrole(string nickname,system.guid usid)開通用戶角色
public bool disableuserrole(string nickname,system.guid usid)禁用用戶角色
public bool removerole(string nickname,system.guid usid)刪除用戶角色
public bool isinrole(string nickname,string role,system.guid usid)判斷某用戶是否具備某權限
public bool isroleenabled(string nickname,string role,system.guid usid)判斷用戶角色是否被開通
(5)daconfig
為了簡化以上各個類對數據庫訪問時參數設置,特增設daconfig類。該類了從配置文件中讀取數據庫連接字符串,即獲取uia子系統中數據庫服務器所在的位置,數據庫的名稱,用戶名和密碼,將這些內容封裝起來直接提供給其他類訪問數據庫時調用(為數據訪問層中的函數調用準備參數),簡化了其他類中數據訪問代碼。 
六、總結:
通過小組各成員的努力,系統基本成形,基本實現預期功能。通過此次畢業設計,我對.net技術有了一定的了解,在數據庫的設計方面積累了寶貴的經驗。隨著開發過程的不斷深入,我對軟件開發有了更加深刻的認識,動手能力也得到了很好的鍛煉。在豐富知識和積累經驗的同時,我的團結協作工作能力也在小組成員的不斷交流中得到提高。這些都將使我在今后的學習工作中大受裨益。但由于個人能力有限,時間倉促,系統尚有不足之處,請各位老師提出寶貴意見。 
七、致謝:
本次畢業設計能夠順利完成離不開我們指導老師鄒顯春老師的指導和幫助,盧心紅老師、陳武老師、聞曉老師、李運剛老師在此過程中也給予了極大的幫助,對他們的幫助表示衷心的感謝。還有小組所有成員對我的大力支持,在此對他們表示衷心的感謝!
 
 
主要參考文獻:
[1]凡若切提..net數據服務c#高級編程. 清華大學出版社
[2]溫謙等.c#編程技術.人民郵電出版社
[3]閃四清.sql sever 2000數據庫管理系統.北京希望電子出版社
 
附錄:
附數據訪問層部分源代碼
namespace dataaccess
{
 /// <summary>
 /// daconfig 的摘要說明。
 /// </summary>
 public class daconfig
 {
 
 public static string connectionstring
 {
 get
 {
 return configurationsettings.appsettings["connectionstring"].tostring();
 }
 }
 }
}
using system;
using system.collections;
using system.data;
 
 
using system.data.sqlclient;
using microsoft.applicationblocks.data;
using model;
namespace dataaccess
{
 public class sites
 {
 public int createsite(sitedata site)
 {
 //準備sql參數
 sqlparameter[] ms=new sqlparameter[6];
 ms[0]=new sqlparameter("@siteid",sqldbtype.int);
 ms[1]=new sqlparameter("@sitename",sqldbtype.nvarchar);
 ms[2]=new sqlparameter("@url",sqldbtype.nvarchar);
 ms[3]=new sqlparameter("@siteenabled",sqldbtype.bit);
 ms[4]=new sqlparameter("@rolename",sqldbtype.nvarchar);
 ms[5]=new sqlparameter("@canadminsite",sqldbtype.nvarchar);
 //給參數賦值
 ms[1].value=site.sitename;
 ms[2].value=site.url;
 ms[3].value=site.enabled;
 //插入站點的參數化sql語句
 string sql="insert into tsites(sitename,url,siteenabled) values(@sitename,@url,@siteenabled)";
 //調用dab層的函數執行操作
 int i=sqlhelper.executenonquery(daconfig.connectionstring,commandtype.text,sql,ms);
 //查詢出自動生成的字段值
 sql="select usid,siteid from tsites where [email protected]";
 sqldatareader reader=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,ms);
 while(reader.read())
 {
 site.usid=reader.getguid(0);
 site.siteid=reader.getint32(1);
 }
 //插入站點的角色參數化語句
 sql="insert into troles (siteid,rolename,canadminsite) values(@siteid,@rolename)";
 ms[0].value=site.siteid;
 for(int j=0;j<site.roles.count;j++)
 {
 //給sql參數賦值
 ms[4].value=((sitedata.role)site.roles[j]).rolename;
 ms[5].value=((sitedata.role)site.roles[j]).canadminsite;
 sqlhelper.executenonquery(daconfig.connectionstring,commandtype.text,sql,ms);
 }
 //查詢出該站點的所有角色,并進行數據格式轉換
 sql="select roleid,rolename,canadminsite from troles where [email protected]";
 sqldatareader r2=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,ms);
 while(r2.read())
 {
 site.roles.add(new model.sitedata.role(r2.getint32(0),r2.getstring(1),r2.getboolean(2) ));
 }
 return i;
 }
 //更改用戶信息
 public int updatesite(sitedata site)
 {
 //準備sql參數
 sqlparameter[] ms=new sqlparameter[7];
 ms[0]=new sqlparameter("@usid",sqldbtype.uniqueidentifier);
 ms[1]=new sqlparameter("@siteid",sqldbtype.int);
 ms[2]=new sqlparameter("@sitename",sqldbtype.nvarchar);
 ms[3]=new sqlparameter("@url",sqldbtype.nvarchar);
 ms[4]=new sqlparameter("@enabled",sqldbtype.bit);
 ms[5]=new sqlparameter("@rolename",sqldbtype.nvarchar);
 ms[6]=new sqlparameter("@roleid",sqldbtype.int);
 //給參數賦值
 ms[0].value=site.usid;
 ms[1].value=site.siteid;
 ms[2].value=site.sitename;
 ms[3].value=site.url;
 ms[4].value=site.enabled;
 //修改站點基本信息參數化sql語句
 string sql="update tsites set [email protected],[email protected],[email protected] where [email protected]";
 int i=sqlhelper.executenonquery(daconfig.connectionstring,commandtype.text,sql,ms);
 sql="update troles set [email protected] where [email protected]";
 for(int j=0;j<site.roles.count;j++)
 {
 ms[5].value=((sitedata.role)site.roles[j]).rolename;
 ms[6].value=((sitedata.role)site.roles[j]).roleid;
 sqlhelper.executenonquery(daconfig.connectionstring,commandtype.text,sql,ms);
 }
 return i;
 }
 //刪除一個站點
 public int removesite(system.guid usid)
 {
 //準備sql參數
 sqlparameter[] ms=new sqlparameter[1];
 ms[0]=new sqlparameter("@usid",sqldbtype.uniqueidentifier);
 ms[0].value=usid;
 //參數化sql語句
 string sql="delete from tsites where [email protected]";
 //調用dab層函數執行操作
 return sqlhelper.executenonquery(daconfig.connectionstring,commandtype.text,sql,ms);
 }
 //查詢站點信息
 public sitedata getsite(system.guid usid)
 {
 //準備sql參數
 sqlparameter[] ms=new sqlparameter[2];
 ms[0]=new sqlparameter("@usid",sqldbtype.uniqueidentifier);
 ms[1]=new sqlparameter("@siteid",sqldbtype.int);
 ms[0].value=usid;
 //參數化sql語句
 string sql="select usid,siteid,sitename,url,siteenabled from tsites where [email protected]";
 //調用dab層函數執行操作
 sqldatareader reader=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,ms);
 sitedata data=null;
 while(reader.read())
 {
 data=new sitedata(reader.getguid(0),reader.getint32(1),reader.getstring(2),reader.getstring(3),reader.getboolean(4));
 }
 //參數化sql語句
 sql="select roleid,rolename,canadminsite from troles where [email protected]";
 ms[1].value=data.siteid;
 //調用dab層函數執行操作
 sqldatareader r2=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,ms);
 while(r2.read() )
 {
 data.roles.add(new sitedata.role(r2.getint32(0),r2.getstring(1),r2.getboolean(2)));
 }
 return data;
 }
 //查詢所有的用戶
 public ilist listsites()
 {
 //返回值是一個鏈表
 ilist ret=new arraylist();
 sqlparameter[] ms=new sqlparameter[1];
 ms[0]=new sqlparameter("@siteid",sqldbtype.int);
 //參數化sql語句
 string sql="select usid,siteid,sitename,url,siteenabled from tsites ";
 //調用dab層函數執行操作
 sqldatareader reader=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,null);
 while(reader.read())
 {
 sitedata data=null; 
 data=new sitedata(reader.getguid(0),reader.getint32(1),reader.getstring(2),reader.getstring(3),reader.getboolean(4));
 sql="select roleid,rolename,canadminsite from troles where [email protected]";
 ms[0].value=data.siteid;
 //調用dab層函數執行操作
 sqldatareader r2=sqlhelper.executereader(daconfig.connectionstring,commandtype.text,sql,ms);
 while(r2.read() )
 {
 //進行格式轉換,并插入鏈表
 data.roles.add(new sitedata.role(r2.getint32(0),r2.getstring(1),r2.getboolean(2)));
 }
 ret.add(data);
 }
 return ret;
 }
 }
}