利用ASP.NET窗体身份验证机制实现自定义Web身份和角色认证

时间:2022-04-07 02:32:04

利用ASP.NET窗体身份验证机制实现自定义Web身份和角色认证

摘 要:用户身份验证和用户授权是Web站点功能的重要组成部分。在应用进行Web开发时,目前通常都是自己编码采用Cookie+Session的方式实现身份验证和用户授权的功能。本文将针对如何利用窗体身份验证机制实现自定义Web身份和角色认证进行简要介绍。

关键字:;FormsAuthentication

用户身份验证和用户授权一般来说都是Web站点和基于浏览器的应用程序的重要功能。这里验证和授权是不同的概念,验证(Authentication)是指"证明你确实是你所说的人",通常是提供一个用户名和口令,然后与持久存储(比如数据库)中的用户名和口令进行对比。授权(Authorization)是指"是否有足够的权限做某件事",此时身份已经被证明过了,授权通常与用户组或者用户级别联系起来,不同的用户组拥有不同的权限(访问特定页面或者执行特定操作)。下面将从窗体身份验证机制和如何利用其实现自定义Web身份和角色认证两个方面进行介绍。

一窗体身份验证机制

在应用进行Web开发的时候,尤其是刚接触.NET时,一般会根据要求,自己编码采用Cookie+Session的方式实现身份验证和用户授权的功能。其实为我们提供了一整套的验证和授权机制,只不过主要基于两个原因我们起初都不使用.NET提供的这套机制,一是我们的Web都要使用自定义的数据库用户表,而不是使用安全机制在App_Data目录下自动生成的ASPNetDB.mdf中的一系列数据表;除此以外,还有一个原因,就是.NET 验证机制提供的相应用户信息太少了,当在页面后置代码中使用User属性时,其Identity属性只有一个Name与用户数据相关(AuthenticationType与IsAuthenticated都是与验证相关),而很多时候我们都需要许多额外的用户数据。

其实这只是因为我们还不是十分了解的安全机制所产生的一个误解罢了,以为使用的验证机制和登录控件就一定要使用其附带的数据表,以为Identity就只能携带一个Name属性。实际上,.NET的安全机制除了验证以外,还包括MemberShip、Profile、Role等几个部分,我们完全可以只使用它的验证机制,而绕过它的MemberShip、Profile和Role,来实现通常我们用Cookie+Session来完成的功能,而且更加高效和安全。

我们在使用验证机制时一般都使用的是基于窗体的验证和授权机制(FormsAuthentication),只要在web.config文件中进行配置,那么就将使用基于窗体的验证和授权机制,主要通过FormsAuthenticationModule这个类来执行。与此同时,我们还可以在配置节中为其配置诸如登录页面、默认页面等信息。在配置节中进行访问授权规则的设置。

该机制的控制流程一般按照下面步骤完成:

1.用户访问某个页面。

2.服务器寻找包含验证信息的cookie,如果没有找到用户将被重定向到登陆页面。

3.浏览器请求浏览登录页面,服务器进行响应。

4.用户输入并且提交数据。

5.服务器通过验证用户的信息,登陆页面将创建一个包含认证票据(formauthenticationticket)的cookie。默认情况下会使用Membership和RoleManager进行。

6.用户验证成功,服务器重新让浏览器指向ReturUrl所指定的页面。

7.在重定向的同时,浏览器向重定向页面发送请求,请求包含验证信息的cookie。

8.FormsAuthenticationModule类对包含身份验证信息的cookie进行验证,验证成功后,将得到当前的用户信息,并传送给HttpContext对象。

9.验证成功后,允许访问页面。

在此过程中,FormsAuthenticationModule类会创建一个GenericPrincipal的对象(在后台中为FormsAuthentication.User),然后把它存入HttpContext中。GenericPrincipal包含一个FormsIdentity的实例的引用(在后台中为FormsAuthentication.User.Identity),FormsIdentity实例包含了用户的信息。一般会通过FormsAuthentication来替我们完成上述工作。

二、实习自定义Web身份和角色认证

通过对窗体身份验证和授权机制进行了解后可知,如要解决前面提到的两个问题,首先要绕开Membership和RoleManager,这样可以使用自定义的验证逻辑和数据进行用户身份验证,实现过程需要调用FormsAuthentication的.SetAuthCookie或RedirectFromLoginPage方法,或者手动创建验证Cookie。

另一方面如果要在认证体系中额外存放数据则要对GenericPrincipal和FormsIdentity进行重构,以创建满足自身需求的Principal和Identity。如下图所示的CustomIdentity在实现了接口IIdentity的基础上,又增加了属性PersonName,其值可以根据其Ticket的UserName属性值(即登录时的用户标示)获取。

如果站点需要进一步实现页面的授权验证,则需要在自定义CustomPrincipal类的IsInRole方法中实现。

定义了实现这两个接口的对象之后,我们还需要把它嵌入到应用程序的生命周期中,具体的做法就是挂接到HttpModule或者是重写Global.asax 中的事件,这里我们采用了重写Global.asax事件的方式,因此创建一个Global.asax文件,然后在应用程序的PostAuthenticateRequest事件中用我们自定义的CustomPrincipal和CustomIdentity替换掉默认的IPrincipal和IIdentity实现。

通过以上处理,我们就可以在使用自定义的用户身份和角色验证逻辑进行用户身份和角色验证的基础上,应用窗体身份验证和授权机制来进行Web站点的用户身份和授权验证了。

参考文献:

[1] S.WALTHER。3.5揭秘(卷2)。人民邮电出版社,2009

[2] 刘霓。基于.NET的用户认证模块设计。中国西部科技,2008(2)

[3] 郑耀东。2.0 编程指南。人民邮电出版社,2007

上一篇:网络谣言对大学生的影响及对策分析 下一篇:英美文学课程设置与传媒类院校比较文化模式的...