目 录
一 引言……………………………………………………………………………………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;
}
}
}