Asp.net中基于角色验证授权

Asp.net的身份验证有有三种,分别是”Windows | Forms | Passport”,其中
又以Forms验证用的最多,也最灵活。
Forms 验证方式对基于用户的验证授权提供了很好的支持,可以通过一个登
录页面验证用户的身份,将此用户的身份发回到客户端的Cookie,之后此用户再
访问这个web应用就会连同这个身份Cookie一起发送到服务端。服务端上的授权
设置就可以根据不同目录对不同用户的访问授权进行控制了。
问题来了,在实际是用中我们往往需要的是基于角色,或者说基于用户组的
验证和授权。对一个网站来说,一般的验证授权的模式应该是这样的:根据实际
需求把用户分成不同的身份,就是角色,或者说是用户组,验证过程不但要验证
这个用户本身的身份,还要验证它是属于哪个角色的。而访问授权是根据角色来
设置的,某些角色可以访问哪些资源,不可以访问哪些资源等等。要是基于用户
来授权访问将会是个很不实际的做法,用户有很多,还可能随时的增减,不可能
在配置文件中随时的为不断增加的新用户去增加访问授权的。
下面大概的看一下Forms的过程。
Forms身份验证基本原理:
一 身份验证
要采用Forms身份验证,先要在应用程序根目录中的Web.config中做相应的设
置:

1<authentication mode=”forms”>
2    <forms name=”.ASPXAUTH “ loginUrl=”/login.aspx” timeout=”30”
3path= “/”>
4    </forms>
5</authentication>

其中<authentication mode= “forms”> 表示本应用程序采用Forms验证方
式。
1. <forms>标签中的name表示指定要用于身份验证的 HTTP Cookie。默认
情况下,name 的值是 .ASPXAUTH。采用此种方式验证用户后,以此用户的信
息建立一个FormsAuthenticationTicket类型的身份验证票,再加密序列化为一个字
符串,最后将这个字符串写到客户端的name指定名字的Cookie中.一旦这个Cook-
ie写到客户端后,此用户再次访问这个web应用时会将连同Cookie一起发送到服务
端,服务端将会知道此用户是已经验证过的.
再看一下身份验证票都包含哪些信息呢,我们看一下FormsAuthentication-
Ticket类:
CookiePath: 返回发出 Cookie 的路径。注意,窗体的路径设置为 /。由于窗
体区分大小写,这是为了防止站点中的 URL 的大小写不一致而采取的一种保护
措施。这在刷新 Cookie 时使用
Expiration: 获取 Cookie 过期的日期/时间。
IsPersistent: 如果已发出持久的 Cookie,则返回 true。否则,身份验证
Cookie 将限制在浏览器生命周期范围内。
IssueDate: 获取最初发出 Cookie 的日期/时间。
Name: 获取与身份验证 Cookie 关联的用户名。
UserData :获取存储在 Cookie 中的应用程序定义字符串。
Version: 返回字节版本号供将来使用。
2. <forms>标签中的loginUrl指定如果没有找到任何有效的身份验证 Cookie,
为登录将请求重定向到的 URL。默认值为 default.aspx。loginUrl指定的页面就是
用来验证用户身份的,一般此页面提供用户输入用户名和密码,用户提交后由程序
来根据自己的需要来验证用户的合法性(大多情况是将用户输入信息同数据库中
的用户表进行比较),如果验证用户有效,则生成同此用户对应的身份验证票,写到
客户端的Cookie,最后将浏览器重定向到用户初试请求的页面.一般是用FormsAu-
thentication.RedirectFromLoginPage 方法来完成生成身份验证票,写回客户端,浏览
器重定向等一系列的动作.

public static void RedirectFromLoginPage( string userName, bool createPersistent-
Cookie, string strCookiePath );


其中:
userName: 就是此用户的标示,用来标志此用户的唯一标示,不一定要映射到
用户账户名称.
createPersistentCookie: 标示是否发出持久的 Cookie。
若不是持久Cookie,Cookie的有效期Expiration属性有当前时间加上web.
config中timeout的时间,每次请求页面时,在验证身份过程中,会判断是否过
了有效期的一半,要是的话更新一次cookie的有效期;若是持久cookie,Expi-
ration属性无意义,这时身份验证票的有效期有cookie的Expires决定,Redirect-
FromLoginPage方法给Expires属性设定的是50年有效期。
strCookiePath: 标示将生成的Cookie的写到客户端的路径,身份验证票中保
存这个路径是在刷新身份验证票Cookie时使用(这也是生成Cookie的Path),若
没有strCookiePath 参数,则使用web.config中 path属性的设置。
这里可以看到,此方法参数只有三个,而身份验证票的属性有七个,不足的四个
参数是这么来的:
IssueDate: Cookie发出时间由当前时间得出,
Expiration:过期时间由当前时间和下面要说的<forms>标签中timeout参数算
出。此参数对非持久性cookie有意义。
UserData: 这个属性可以用应用程序写入一些用户定义的数据,此方法没有用
到这个属性,只是简单的将此属性置为空字符串,请注意此属性,在后面我们将要使
用到这个属性。
Version: 版本号由系统自动提供.
RedirectFromLoginPage方法生成生成身份验证票后,会调用FormsAuthenti-
cation.Encrypt 方法,将身份验证票加密为字符串,这个字符串将会是以.ASPX-
AUTH为名字的一个Cookie的值。这个Cookie的其它属性的生成:Domain,
Path属性为确省值,Expires视createPersistentCookie参数而定,若是持久cookie,
Expires设为50年以后过期;若是非持久cookie,Expires属性不设置。
生成身份验证Cookie后,将此Cookie加入到Response.Cookies中,等待发送
到客户端。
最后RedirectFromLoginPage方法调用FormsAuthentication.GetRedirectUrl 方法
获取到用户原先请求的页面,重定向到这个页面。
3. <forms>标签中的timeout和path,是提供了身份验证票写入到Cookie过期时
间和默认路径。
以上就是基于Forms身份验证的过程,它完成了对用户身份的确认。下面介
绍基于Forms身份验证的访问授权。
二 访问授权
验证了身份,是要使用这个身份,根据不同的身份我们可以进行不同的操
作,处理,最常见的就是对不同的身份进行不同的授权,Forms验证就提供这样
的功能。Forms授权是基于目录的,可以针对某个目录来设置访问权限,比如,
这些用户可以访问这个目录,那些用户不能访问这个目录。
同样,授权设置是在你要控制的那个目录下的web.config文件中来设置:

<authorization>
2    <allow users=”comma-separated list of users”
3        roles=”comma-separated list of roles”
4        verbs=”comma-separated list of verbs” />
5     <deny users=”comma-separated list of users”
6        roles=”comma-separated list of roles”
7        verbs=”comma-separated list of verbs” />
8</authorization>

<allow>标签表示允许访问,其中的属性
1. users:一个逗号分隔的用户名列表,这些用户名已被授予对资源的访问权
限。问号 (?) 允许匿名用户;星号 (*) 允许所有用户。
2. roles:一个逗号分隔的角色列表,这些角色已被授予对资源的访问权限。
3. verbs:一个逗号分隔的 HTTP 传输方法列表,这些 HTTP 传输方法已
被授予对资源的访问权限。注册到 ASP.NET 的谓词为 GET、HEAD、POST 和
DEBUG。
<deny>标签表示不允许访问。其中的属性同上面的。
在运行时,授权模块迭代通过 <allow> 和 <deny> 标记,直到它找到适合特
定用户的第一个访问规则。然后,它根据找到的第一项访问规则是 <allow> 还是
<deny> 规则来允许或拒绝对 URL 资源的访问。Machine.config 文件中的默认身
份验证规则是 <allow users=”*”/>,因此除非另行配置,否则在默认情况下会
允许访问。
那么这些user 和roles又是如何得到的呢?下面看一下授权的详细过程:
1. 一旦一个用户访问这个网站,就行登录确认了身份,身份验证票的cook-
ie也写到了客户端。之后,这个用户再次申请这个web的页面,身份验证票的
cookie就会发送到服务端。在服务端,asp.net为每一个http请求都分配一个Htt-
pApplication对象来处理这个请求,在HttpApplication.AuthenticateRequest事件
后,安全模块已建立用户标识,就是此用户的身份在web端已经建立起来,这个
身份完全是由客户端发送回来的身份验证票的cookie建立的。
2. 用户身份在HttpContext.User 属性中,在页面中可以通过Page.Context 来获
取同这个页面相关的HttpContext对象。对于Forms验证,HttpContext.User属性是
一个GenericPrincipal类型的对象,GenericPrincipal只有一个公开的属性Identity,
有个私有的m_role属性,是string[]类型,存放此用户是属于哪些role的数组,还
有一个公开的方法IsInRole(string role),来判断此用户是否属于某个角色。
由于身份验证票的cookie中根本没有提供role这个属性,就是说Forms身份验

证票没有提供此用户的role信息,所以,对于Forms验证,在服务端得到的Gener-
icPrincipal 用户对象的m_role属性永远是空的。
3. GenericPrincipal. Identity 属性是一个FormsIdentity类型的对象,这个对象有
个Name属性,就是此用户的标示,访问授权就是将此属性做为user来进行授权验
证的。FormsIdentity还有一个属性,就是Ticket属性,此属性是身份验证票Form-
sAuthenticationTicket类型,就是之前服务器写到客户端的身份验证票。
服务器在获取到身份验证票FormsAuthenticationTicket对象后,查看这个身
份验证票是不是非持久的身份验证,是的话要根据web.config中timeout属性设置
的有效期来更新这个身份验证票的cookie(为避免危及性能,在经过了超过一半
的指定时间后更新该 Cookie。这可能导致精确性上的损失。持久性 Cookie 不超
时。)
4. 在HttpApplication.ResolveRequestCache事件之前,asp.net开始取得用户请
求的页面,建立HttpHandler控制点。这就意味着,在HttpApplication.ResolveRe-
questCache事件要对用户访问权限就行验证,看此用户或角色是否有权限访问这
个页面,之后在这个请求的生命周期内再改变此用户的身份或角色就没有意义
了。
以上是Forms验证的全过程,可以看出,这个Forms验证是基于用户的,没有
为角色的验证提供直接支持。身份验证票FormsAuthenticationTicket 中的Name属
性是用户标示,其实还有一个属性UserData,这个属性可以由应用程序来写入自
定义的一些数据,我们可以利用这个字段来存放role的信息,从而达到基于角色
验证的目的。
Forms身份验证基于角色的授权
一 身份验证
在web.config的<authentication>的设置还是一样:


1<authentication mode=”forms”>
2    <forms name=”.ASPXAUTH “ loginUrl=”/login.aspx” timeout=”30”
3path= “/”>
4    </forms>
5</authentication>

/login.aspx验证用户合法性页面中,在验证了用户的合法性后,还要有个取
得此用户属于哪些role的过程,这个看各个应用的本身如何设计的了,一般是在
数据库中会有个use_role表,可以从数据库中获得此用户属于哪些role,在此不深
究如何去获取用户对应的role,最后肯定能够获得的此用户对应的所有的role用逗
号分割的一个字符串。
在上面的非基于角色的方法中,我们用了FormsAuthentication.RedirectFrom-
LoginPage 方法来完成生成身份验证票,写回客户端,浏览器重定向等一系列的动
作。这个方法会用一些确省的设置来完成一系列的动作,在基于角色的验证中我
们不能用这一个方法来实现,要分步的做,以便将一些定制的设置加进来:
1. 首先要根据用户标示,和用户属于的角色的字符串来创建身份验证票

public FormsAuthenticationTicket(
int version, //设为1
string name, //用户标示
DateTime issueDate, //Cookie 的发出时间, 设置为 DateTime.Now
DateTime expiration, //过期时间
bool isPersistent, //是否持久性(根据需要设置,若是设置为持久性,在发出
cookie时,cookie的Expires设置一定要设置)
string userData, //这里用上面准备好的用逗号分割的role字符串
string cookiePath // 设为”/”,这要同发出cookie的路径一致,因为刷新cookie
要用这个路径
);
FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket
(1,”kent”,DateTime.Now, DateTime.Now.AddMinutes(30), false,UserRoles,”/”)
;

2. 生成身份验证票的Cookie
2.1 将身份验证票加密序列化成一个字符串
string HashTicket = FormsAuthentication.Encrypt (Ticket) ;
2.2 生成cookie
HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookie-
Name, HashTicket) ;
FormsAuthentication.FormsCookieName 是用来获取web.config中设置的身份
验证cookie的名字,缺省为” .ASPXAUTH”.
若身份验证票中的isPersistent属性设置为持久类,则这个cookie的Expires属性
一定要设置,这样这个cookie才会被做为持久cookie保存到客户端的cookie文件中.
3. 将身份验证票Cookie输出到客户端
通过Response.Cookies.Add(UserCookie) 将身份验证票Cookie附加到输出的
cookie集合中,发送到客户端.
4. 重定向到用户申请的初试页面.

验证部分代码(这部分代码是在login.aspx页面上点击了登录按钮事件处理代
码):
1private void Buttonlogin_Click(object sender, System.EventArgs e)
2{
3     string user = TextBoxUser.Text; //读取用户名
4     string password = TextBoxPassword.Text; //读取密码
5     if(Confirm(user,password) == true) //confirm方法用来验证用户合法性的
6    {
7         string userRoles = UserToRole(user); //调用UserToRole方法来获取role字符
8
9         FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket
10(1,user,DateTime.Now,          DateTime.Now.AddMinutes(30), false,userRoles,”/”)
11; //建立身份验证票对象
12         string HashTicket = FormsAuthentication.Encrypt (Ticket) ; //加密序列化验证
13票为字符串
14         HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCook-
15ieName, HashTicket) ;
16//生成Cookie
17 Context.Response.Cookies.Add (UserCookie) ; //输出Cookie
18         Context.Response.Redirect (Context.Request[“ReturnUrl”]) ; // 重定向到用
19户申请的初始页面
20     }

21    else {
22        // 用户身份未被确认时的代码
23    }

24}

25//此方法用来验证用户合法性的
26private bool Confirm(string user,string password)
27{
28    //相应的代码
29}

30//此方法用来获得的用户对应的所有的role用逗号分割的一个字符串
31private string UserToRole(string user)
32{
33    //相应的代码
34}

二 基于角色访问授权
这里我们要做的是,将客户端保存的身份验证票中UserData中保存的表示角色
的信息恢复到在服务端表示用户身份的GenericPrincipal对象中(记住,原来的验证
过程中, GenericPrincipal对象只包含了用户信息,没有包含role信息)
一个Http请求的过程中,HttpApplication.AuthenticateRequest事件表示安全模
块已建立用户标识,就是此用户的身份在web端已经建立起来, 在这个事件之后
我们就可以获取用户身份信息了.
在HttpApplication.ResolveRequestCache事件之前,asp.net开始取得用户请求
的页面,建立HttpHandler控制点,这时就已经要验证用户的权限了,所以恢复用户
角色的工作只能在HttpApplication.AuthenticateRequest事件和HttpApplication.Re-
solveRequestCache事件之间的过程中做.
我们选择Application_AuthorizeRequest事件中做这个工作,可以在global.asax文
件中处理HttpApplication的所有的事件,代码如下:


1protected void Application_AuthorizeRequest(object sender, System.EventArgs e)
2{
3    HttpApplication App = (HttpApplication) sender;
4     HttpContext Ctx = App.Context ; //获取本次Http请求相关的HttpContext对
5
6    if (Ctx.Request.IsAuthenticated == true) //验证过的用户才进行role的处理
7    {
8        FormsIdentity Id = (FormsIdentity)Ctx.User.Identity ;
9        FormsAuthenticationTicket Ticket = Id.Ticket ; //取得身份验证票
10       string[] Roles = Ticket.UserData.Split (‘,’) ; //将身份验证票中的role数
11据转成字符串数组
12        Ctx.User = new GenericPrincipal (Id, Roles) ; //将原有的Identity加上角色
13信息新建一个GenericPrincipal表示当前用户,这样当前用户就拥有了role信息
14    }

15}


访问者同时具有了user和role信息,就可以据此在web.config中用role来控制用
户的访问权限了.

已标记关键词 清除标记
相关推荐
ASP.NET ASP.NET 概述 ASP.NET 是一个统一的 Web 开发模型,它包括您使用尽可能少的代码生成企业级 Web 应用程序所必需的各种服务。ASP.NET 作为 .NET Framework 的一部分提供。当您编写 ASP.NET 应用程序的代码时,可以访问 .NET Framework 的类。您可以使用与公共语言运行库 (CLR) 兼容的任何语言来编写应用程序的代码,这些语言包括 Microsoft Visual Basic、C#、JScript .NET 和 J#。使用这些语言,可以开发利用公共语言运行库、类型安全、继承等方面的优点的 ASP.NET 应用程序。 ASP.NET 包括: 页和控件框架 ASP.NET 编译器 安全基础结构 状态管理功能 应用程序配置 运行状况监视和性能功能 调试支持 XML Web services 框架 可扩展的宿主环境和应用程序生命周期管理 可扩展的设计器环境 页和控件框架 ASP.NET 页和控件框架是一种编程框架,它在 Web 服务器上运行,可以动态地生成和呈现 ASP.NET 网页。可以从任何浏览器或客户端设备请求 ASP.NET 网页,ASP.NET 会向请求浏览器呈现标记(例如 HTML)。通常,您可以对多个浏览器使用相同的页,因为 ASP.NET 会为发出请求的浏览器呈现适当的标记。但是,您可以针对诸如 Microsoft Internet Explorer 6 的特定浏览器设计 ASP.NET 网页,并利用该浏览器的功能。ASP.NET 支持基于 Web 的设备(如移动电话、手持型计算机和个人数字助理 (PDA))的移动控件。 ASP.NET 网页是完全面向对象的。在 ASP.NET 网页,可以使用属性、方法和事件来处理 HTML 元素。ASP.NET 页框架为响应在服务器上运行的代码的客户端事件提供统一的模型,从而使您不必考虑基于 Web 的应用程序固有的客户端和服务器隔离的实现细节。该框架还会在页处理生命周期自动维护页及该页上控件的状态。有关更多信息,请参见 ASP.NET 网页概述。 使用 ASP.NET 页和控件框架还可以将常用的 UI 功能封装成易于使用且可重用的控件。控件只需编写一次,即可用于许多页并集成到 ASP.NET 网页。这些控件在呈现期间放入 ASP.NET 网页ASP.NET 页和控件框架还提供各种功能,以便可以通过主题和外观来控制网站的整体外观和感觉。可以先定义主题和外观,然后在页面级或控件级应用这些主题和外观。有关更多信息,请参见 ASP.NET 主题和外观概述。 除了主题外,还可以定义母版页,以使应用程序的页具有一致的布局。一个母版页可以定义您希望应用程序的所有页(或一组页)所具有的布局和标准行为。然后可以创建包含要显示的页特定内容的各个内容页。当用户请求内容页时,这些内容页与母版页合并,产生将母版页的布局与内容页的内容组合在一起的输出。有关更多信息,请参见 ASP.NET 母版页概述。 ASP.NET 编译器 所有 ASP.NET 代码都经过了编译,可提供强类型、性能优化和早期绑定以及其他优点。代码一经编译,公共语言运行库会进一步将 ASP.NET 编译为本机代码,从而提供增强的性能。 ASP.NET 包括一个编译器,该编译器将包括页和控件在内的所有应用程序组件编译成一个程序集,之后 ASP.NET 宿主环境可以使用该程序集来处理用户请求。有关更多信息,请参见 ASP.NET 编译概述。 安全基础结构 除了 .NET 的安全功能外,ASP.NET 还提供了高级的安全基础结构,以便对用户进行身份验证授权,并执行其他与安全相关的功能。您可以使用由 IIS 提供的 Windows 身份验证对用户进行身份验证,也可以通过您自己的用户数据库使用 ASP.NET Forms 身份验证ASP.NET 成员资格来管理身份验证。此外,可以使用 Windows 组或您自己的自定义角色数据库(使用 ASP.NET 角色)来管理 Web 应用程序的功能和信息方面的授权。您可以根据应用程序的需要方便地移除、添加或替换这些方案。有关更多信息,请参见下列主题: ASP.NET 网站安全性 使用成员资格管理用户 使用角色管理授权 Forms 身份验证提供程序 ASP.NET 始终使用特定的 Windows 标识运行,因此,您可以通过使用 Windows 功能(例如 NTFS 访问控制列表 (ACL)、数据库权限等等)来保护应用程序的安全。有关 ASP.NET 标识的更多信息,请参见配置 ASP.NET 进程标识和 ASP.NET 模拟。 状态管理功能 ASP.NET 提供了内部状态管理功能,它使您能够存储页请求期间的信息,例如客户信息或购物车的内容。您可以保存和管理应用程序特定、会话特定、页特定、用户特定和开发人员定义的信息。此信息可以独立于页上的任何控件。 ASP.NET 提供了分布式状态功能,使您能够管理一台计算机或数台计算机上同一应用程序的多个实例的状态信息。有关更多信息,请参见 ASP.NET 状态管理概述。 ASP.NET 配置 通过 ASP.NET 应用程序使用的配置系统,可以定义 Web 服务器、网站或单个应用程序的配置设置。您可以在部署 ASP.NET 应用程序时定义配置设置,并且可以随时添加或修订配置设置,且对运行的 Web 应用程序和服务器具有最小的影响。ASP.NET 配置设置存储在基于 XML 的文件。由于这些 XML 文件是 ASCII 文本文件,因此对 Web 应用程序进行配置更改比较简单。您可以扩展配置方案,使其符合自己的要求。有关更多信息,请参见 ASP.NET 配置概述。 运行状况监视和性能功能 ASP.NET 包括可监视 ASP.NET 应用程序的运行状况和性能的功能。使用 ASP.NET 运行状况监视可以报告关键事件,这些关键事件提供有关应用程序的运行状况和错误情况的信息。这些事件显示诊断和监视特征的组合,并在记录哪些事件以及如何记录事件等方面提供了高度的灵活性。有关更多信息,请参见 ASP.NET 运行状况监视概述。 ASP.NET 支持两组可供应用程序访问的性能计数器: ASP.NET 系统性能计数器组 ASP.NET 应用程序性能计数器组 有关更多信息,请参见监视 ASP.NET 应用程序性能。
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页