一、概述
1.ADO.Net简述
随着互联网和应用程序开发的发展演变,越来越多的应用程序要基于 Web 应用程序模型,它们使用 XML来对数据进行编码,然后再通过网络连接将数据传递出去。新的Web 应用程序也越来越趋于松散地耦合,它们以 HTTP作为层间进行通信的结构,并且必须显式处理请求之间的维护状态。在此情况下,曾经的客户端/服务器时代的连接、紧耦合的编程模型已经不再适用。因为在此模型下,连接会在程序的整个生存期中始终保持打开,不需要对状态进行特殊的处理。
ADO.Net是一组.Net 应用程序开发人员用于数据访问服务的类,为创建分布式数据共享应用程序提供了一组丰富的组件。ADO.Net的设计是为了满足数据访问提供全新的编程模型。这种数据访问模型要求:具有断开式数据结构;紧密集成XML支持;具有能够组合来自多个不同数据源的数据的通用数据表示形式;以及具有为了与数据库交互而优化的功能。
ADO.Net中对数据的访问和处理主要使用两个组件:.Net Framework 数据提供程序和DataSet。
.Net Framework 数据提供程序是专门为数据处理以及快速的数据访问而设计的组件,它主要由四部分组成,如图1所示:Connection对象、Command 对象、DataReader 以及DataAdapter 。Connection 对象提供与数据源的连接。Command 对象能够访问用于返回数据、修改数据、运行存储过程以及发送或检索参数信息的数据库命令。DataReader 从数据源中提供高性能的数据流。最后,DataAdapter 提供了连接 DataSet 对象和数据源的桥梁。DataAdapter 使用 Command 对象在数据源中执行 SQL 命令,以便将数据加载到 DataSet 中,并使对 DataSet 中数据的更改与数据源保持一致。
图1 .Net Framework 数据提供程序组成图
DataSet类是ADO.Net中最核心的成员之一,也是各种开发基于.Net平台程序语言开发数据库应用程序最常接触的类。DataSet是数据的一种内存驻留表示形式,也可以把它看作是数据的脱机容器,但并不包含数据库连接。事实上,存储在DataSet中的数据也不一定来自数据库,但无论它包含的数据来自什么数据源,都会提供一致的关系编程模型。DataSet由一组数据表组成,每个表都有相应的一些数据行和列,如图2所示。
图2 DataSet组成图
DataReader相比DataSet而言,DataReader提供了一种快速的数据访问,然而它的缺点也是显而易见的。DataReader是只读的,而且当指针移动到下一行就无法查看上一行数据。而DataSet可以自由移动指针,并且由于处理的是脱机数据,因此其在多层应用程序中非常有用。
在开发基于.Net平台的数据库应用程序时,常常要把应用程序分层,常见的模型是三层结构:表示层、数据服务层和数据库本身。在这种模型中(如图3所示),一般并不直接对数据库操作(直接在程序中调用存储过程等除外),而是先完成数据连接和通过数据适配器将数据填充至DataSet对象中,然后客户层通过读取DataSet来获得需要的数据。
图3 三层应用程序结构图
同样更新数据库中数据,也是首先更新DataSet,然后再通过DataSet来更新数据库中对应的数据。DataSet在客户层实现读取、更新数据库等过程中起到了中间层的作用。DataSet与不同数据源的连接关系如图4所示。
图4 DataSet与不同数据源的连接关系图
DataSet的使用方法主要有以下三种:
⑴ 用数据库中的数据通过DataAdapter对象填充DataSet。例如:
string select="SELECT CustomerID,CompanyName FROM Customers";
SqlConnection conn=ndw SqlConnection(source);
SqlDataAdapter da=new SqlDataAdapter(select,conn);
DataSet ds=new DataSet();
da.Fill(ds,"Customers");
⑵ 通过DataAdapter对象操作DataSet实现更新数据库。例如:
sql_cb=new SqlCommandBuilder(da);
datagrid1.SetDataBinding(ds, " Customers ");
……
da.Update(ds,"Customers");
ds.Tables["Customers"].AcceptChanges();
⑶ 把XML数据流或文本加载到DataSet。例如:
DataSet ds=new DataSet();
ds.ReadXml(".\\users.xml");
2. XML简介
可扩展标记语言(EXtensible Markup Language,简称XML)是一种提供数据描述格式的标记语言。该语言使跨越多个平台进行更准确的内容声明和获得更有意义的搜索结果变得更加容易。虽然XML出现在HTML之后,但XML并不是HTML的替代品,可以将它看作是HTML的补充。HTML设计用来显示数据的,重点是数据的显示和外观。而XML设计用来描述数据的,重点是如何存放数据,它实现了表示与数据的分离。在 HTML 中,使用标记来告诉浏览器将数据显示为粗体或斜体;而在 XML 中,标记只用于描述数据,如用户名、密码和权限。在 XML 中,使用样式表(如可扩展样式表语言 (XSL) 和层叠样式表 (CSS))在浏览器中显示数据。XML 使数据与表示及处理分离开来,通过应用不同的样式表和应用程序,能够根据需要来显示和处理数据。
XML文档使用了自描述的和简单的语法。下面通过一个简单的XML文档的例子来说明它。
<?xml version="1.0" encoding="utf-8" ?>
<users>
<user>
<name>Robert</name>
<password>pwd</password>
<role>Teacher</role>
</user>
<user>
<name>Tom</name>
<password>pwd</password>
<role>Student</role>
</user>
</users>
文档的第1行: XML声明—定义此文档所遵循的XML标准的版本,在这个例子里是1.0版本的标准,使用的是utf-8字符集。
<?xml version="1.0" encoding="utf-8" ?>
文档的第2行是根元素:
<users>
文档的第3至12行描述了根元素的子元素user,而user又包括了name、password 和role三个子元素。
<user>
<name>Robert</name>
<password>pwd</password>
<role>Teacher</role>
</user>
<user>
<name>Tom</name>
<password>pwd</password>
<role>Student</role>
</user>
文档的最后一行是根元素的结束:
</users>
3. .Net角色的安全性
在一些应用程序(比如财务或商务应用程序)中常常要使用到角色来强制策略。例如,应用程序可能根据提出请求的用户是不是指定角色的成员,对要处理的事务大小加以限制。基于角色的安全性也可以用于需要多个批准完成某项操作的应用程序。如一个采购系统,在该系统中,任何雇员均可生成采购请求,但只有采购代理人可以将此请求转换成可发送给供应商的采购订单。
基于角色的安全性与Windows帐户、Microsoft PassPort或ASP.Net Cookies验证一起使用可以很好地解决基于Web资源的访问管理。Web站点在用户注册之前要限制其对某些页面或者站点提供的某些功能的访问,而且只有用户成为VIP用户之后才能访问站点上的需付费内容。在众多的方法中,基于角色的安全性尤其适用于ASP.Net Web 应用程序,因为大量代码都是基于服务器处理的。
.Net Framework 基于角色的安全性通过生成可供当前线程使用的主体(Principal)信息来提供,并且通过主体可以访问用户的身份(Identity)。用户的身份常常用于映射包括Windows帐户、Passport帐户以及ASP.Net Cookies已验证用户等类型。.Net Framework 应用程序可以根据主体的身份或角色成员条件或者这两者皆有来进行安全决策。角色是具有相同安全权限的用户集合,它也是进行用户管理的单元。一个主体可以是一个或多个角色的成员,因此,应用程序可以使用角色成员条件来确定主体是否有权执行某项请求的操作。相对于单个用户,以角色作为基础对资源和功能进行访问,可以使安全性的管理更加容易。在基于角色的安全性中,当需要增加或者删除用户时只需要在相应角色中添加或删除该用户;当需要对某部分用户的访问权限进行修改时只用简单地修改其所在角色的权限,这样做可以大大简化应用程序,也提供了较好的扩展性和可维护性。
对于基于Windows验证策略进行用户验证,需要将WindowsPrincipal类型用作主体,将WindowsIdentity类型用作身份。通过WindowsIdentity类型可以判断用户是否是某一Windows用户帐户组的成员,然后利用得到的信息来决定是否允许用户对资源和功能的访问。
对于WindowsPrincipal类型和WindowsIdentity类型中的几个重要方法和属性。通过WindowsPrincipal的Identity属性可以获取当前用户的标识,IsInRole方法可以确定当前用户是否属于指定的 Windows 用户组,WindowsIdentity类型中的通用属性如下表所示。
WindowsIdentity类型中的通用属性及说明
属性 |
说明 |
AuthenticationType |
获取用于标识用户身份验证的类型。 |
Groups |
获取当前 Windows 用户所属的组。 |
IsAnonymous |
用于判断系统是否将用户帐户标识为匿名帐户。 |
IsAuthenticated |
用于判断 Windows 是否对用户进行了验证。 |
IsGuest |
用于判断系统是否将用户帐户标识为 Guest 帐户。 |
IsSystem |
用于判断系统是否将用户帐户标识为 System 帐户。 |
Name |
获取用户的 Windows 登录名。 |
Owner |
获取标记所有者的安全标识符 (SID)。 |
Token |
获取用户的 Windows 帐户标记。 |
User |
获取用户的安全标识符 (SID)。 |
二、程序界面详
本例主要实现用户身份验证并由此判断是否转入后台账户数据显示。根据要求设计出程序界面分别如图5、图6所示。
图5 登录验证框
图6登录验证后显示账户列表
当用户选择通过Windows管理员账号登录时,利用基于角色的安全性中Windwos验证策略,可以判断当前用户是否为管理员角色,再决定是否显示后台账号数据界面。当用户输入用户名和密码登录时,则需要进行常规验证。验证的后台数据可以来自数据库、文本文件或者XML文档等。值得注意的是,处于安全性考虑,当用户超过三次验证不通过则应用程序自动退出。
本程序的核心是用户身份的验证功能,可以通过定义一个特定的Users类来实现。Users类应包含如下方法:
IsLogin方法,判断账号和口令是否存在于包含已注册用户信息的XML文档中。
GetLogin方法,返回封装了 GenericIdentity类型数据和用户角色名称的一般主体GenericPrincipal类型数据(GenericIdentity类型数据封装了已注册用户账号名称)。GenericPrincipal类型与GenericIdentity类型之间的关系类似于前面已经介绍到的WindowsPrincipal类型与WindowsIdentity类型。
IsAdministrator方法,利用基于角色的安全性中Windwons验证策略判断当前用户是否为管理员角色。
|