参考
<script type="text/javascript">loadTOCNode(1, 'references');</script>
有关如何使用
<credentials> 部分存储用户和密码来实现基于窗体的简单身份验证的更多信息,请参阅以下 GotDotNet ASP.NET 快速入门示例:
基于窗体的身份验证
http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=/quickstart/aspplus/doc/formsauth.aspx (http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=/quickstart/aspplus/doc/formsauth.aspx)
有关如何使用 XML 文件存储用户和密码来实现基于窗体的身份验证的更多信息,请参阅 .NET Framework 软件开发工具包 (SDK) 文档中的以下主题:
http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=/quickstart/aspplus/doc/formsauth.aspx (http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=/quickstart/aspplus/doc/formsauth.aspx)
使用 XML 用户文件的窗体身份验证
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcookieauthenticationusinganxmlusersfile.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcookieauthenticationusinganxmlusersfile.asp)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcookieauthenticationusinganxmlusersfile.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcookieauthenticationusinganxmlusersfile.asp)
下面大概的看一下
Forms
的过程。
Forms
身份验证基本原理:
一
身份验证
要采用
Forms
身份验证,先要在应用程序根目录中的
Web.config
中做相应的设置
:
<authentication mode="forms">
<forms name=".ASPXAUTH " loginUrl="/login.aspx" timeout="30" path= "/">
</forms>
</authentication>
其中
<authentication mode= "forms">
表示本应用程序采用
Forms
验证方式。
1. <forms>
标签中的
name
表示指定要用于身份验证的
HTTP Cookie
。默认情况下,
name
的值是
.ASPXAUTH
。采用此种方式验证用户后
,
以此用户的信息建立一个
FormsAuthenticationTicket
类型的身份验证票
,
再加密序列化为一个字符串
,
最后将这个字符串写到客户端的
name
指定名字的
Cookie
中
.
一旦这个
Cookie
写到客户端后
,
此用户再次访问这个
web
应用时会将连同
Cookie
一起发送到服务端
,
服务端将会知道此用户是已经验证过的
.
再看一下身份验证票都包含哪些信息呢
,
我们看一下
FormsAuthenticationTicket
类
:
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,
最后将浏览器重定向到用户初试请求的页面
.
一般是用
FormsAuthentication.RedirectFromLoginPage
方法来完成生成身份验证票
,
写回客户端
,
浏览器重定向等一系列的动作
.
public static void RedirectFromLoginPage( string userName, bool createPersistentCookie, string strCookiePath );
其中
:
userName
:
就是此用户的标示
,
用来标志此用户的唯一标示
,
不一定要映射到用户账户名称
.
createPersistentCookie
:
标示是否发出持久的
Cookie
。
若不是持久
Cookie
,
Cookie
的有效期
Expiration
属性有当前时间加上
web.config
中
timeout
的时间,每次请求页面时,在验证身份过程中,会判断是否过了有效期的一半,要是的话更新一次
cookie
的有效期;若是持久
cookie
,
Expiration
属性无意义,这时身份验证票的有效期有
cookie
的
Expires
决定,
RedirectFromLoginPage
方法给
Expires
属性设定的是
50
年有效期。
strCookiePath
:
标示将生成的
Cookie
的写到客户端的路径,身份验证票中保存这个路径是在刷新身份验证票
Cookie
时使用(这也是生成
Cookie
的
Path
),若没有
strCookiePath
参数,则使用
web.config
中
path
属性的设置。
这里可以看到
,
此方法参数只有三个
,
而身份验证票的属性有七个
,
不足的四个参数是这么来的
:
IssueDate
:
Cookie
发出时间由当前时间得出
,
Expiration
:过期时间由当前时间和下面要说的
<forms>
标签中
timeout
参数算出。此参数对非持久性
cookie
有意义。
UserData
:
这个属性可以用应用程序写入一些用户定义的数据
,
此方法没有用到这个属性
,
只是简单的将此属性置为空字符串
,
请注意此属性
,
在后面我们将要使用到这个属性。
Version
:
版本号由系统自动提供
.
RedirectFromLoginPage
方法生成生成身份验证票后,会调用
FormsAuthentication.Encrypt
方法,将身份验证票加密为字符串,这个字符串将会是以
.ASPXAUTH
为名字的一个
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>
<allow users="comma-separated list of users"
roles="comma-separated list of roles"
verbs="comma-separated list of verbs" />
<deny users="comma-separated list of users"
roles="comma-separated list of roles"
verbs="comma-separated list of verbs" />
</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.
一旦一个用户访问这个网站,就行登录确认了身份,身份验证票的
cookie
也写到了客户端。之后,这个用户再次申请这个
web
的页面,身份验证票的
cookie
就会发送到服务端。在服务端,
asp.net
为每一个
http
请求都分配一个
HttpApplication
对象来处理这个请求,在
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
验证,在服务端得到的
GenericPrincipal
用户对象的
m_role
属性永远是空的。
3. GenericPrincipal. Identity
属性是一个
FormsIdentity
类型的对象,这个对象有个
Name
属性,就是此用户的标示,访问授权就是将此属性做为
user
来进行授权验证的。
FormsIdentity
还有一个属性,就是
Ticket
属性,此属性是身份验证票
FormsAuthenticationTicket
类型,就是之前服务器写到客户端的身份验证票。
服务器在获取到身份验证票
FormsAuthenticationTicket
对象后,查看这个身份验证票是不是非持久的身份验证,是的话要根据
web.config
中
timeout
属性设置的有效期来更新这个身份验证票的
cookie
(为避免危及性能,在经过了超过一半的指定时间后更新该
Cookie
。这可能导致精确性上的损失。持久性
Cookie
不超时。)
4.
在
HttpApplication.ResolveRequestCache
事件之前,
asp.net
开始取得用户请求的页面,建立
HttpHandler
控制点。这就意味着,在
HttpApplication.ResolveRequestCache
事件要对用户访问权限就行验证,看此用户或角色是否有权限访问这个页面,之后在这个请求的生命周期内再改变此用户的身份或角色就没有意义了。
以上是
Forms
验证的全过程,可以看出,这个
Forms
验证是基于用户的,没有为角色的验证提供直接支持。身份验证票
FormsAuthenticationTicket
中的
Name
属性是用户标示,其实还有一个属性
UserData
,这个属性可以由应用程序来写入自定义的一些数据,我们可以利用这个字段来存放
role
的信息,从而达到基于角色验证的目的。
Forms
身份验证基于角色的授权
一
身份验证
在
web.config
的
<authentication>
的设置还是一样:
<authentication mode="forms">
<forms name=".ASPXAUTH " loginUrl="/login.aspx" timeout="30" path= "/">
</forms>
</authentication>
/login.aspx
验证用户合法性页面中,在验证了用户的合法性后,还要有个取得此用户属于哪些
role
的过程,这个看各个应用的本身如何设计的了,一般是在数据库中会有个
use_role
表,可以从数据库中获得此用户属于哪些
role
,在此不深究如何去获取用户对应的
role
,最后肯定能够获得的此用户对应的所有的
role
用逗号分割的一个字符串。
在上面的非基于角色的方法中,我们用了
FormsAuthentication.RedirectFromLoginPage
方法来完成生成身份验证票
,
写回客户端
,
浏览器重定向等一系列的动作。这个方法会用一些确省的设置来完成一系列的动作,在基于角色的验证中我们不能用这一个方法来实现,要分步的做,以便将一些定制的设置加进来:
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.FormsCookieName, HashTicket) ;
FormsAuthentication.FormsCookieName
是用来获取
web.config
中设置的身份验证
cookie
的名字
,
缺省为
" .ASPXAUTH".
若身份验证票中的
isPersistent
属性设置为持久类
,
则这个
cookie
的
Expires
属性一定要设置
,
这样这个
cookie
才会被做为持久
cookie
保存到客户端的
cookie
文件中
.
3.
将身份验证票
Cookie
输出到客户端
通过
Response.Cookies.Add(UserCookie)
将身份验证票
Cookie
附加到输出的
cookie
集合中
,
发送到客户端
.
4.
重定向到用户申请的初试页面
.
验证部分代码
(
这部分代码是在
login.aspx
页面上点击了登录按钮事件处理代码
):
private void Buttonlogin_Click(object sender, System.EventArgs e)
{
string user = TextBoxUser.Text; //
读取用户名
string password = TextBoxPassword.Text; //
读取密码
if(Confirm(user,password) == true) //confirm
方法用来验证用户合法性的
{
string userRoles = UserToRole(user); //
调用
UserToRole
方法来获取
role
字符串
FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket (1,user,DateTime.Now, DateTime.Now.AddMinutes(30), false,userRoles,"/") ; //
建立身份验证票对象
string HashTicket = FormsAuthentication.Encrypt (Ticket) ; //
加密序列化验证票为字符串
HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket) ;
//
生成
Cookie
Context.Response.Cookies.Add (UserCookie) ; //
输出
Cookie
Context.Response.Redirect (Context.Request["ReturnUrl"]) ; //
重定向到用户申请的初始页面
}
else
{
//
用户身份未被确认时的代码
}
}
//
此方法用来验证用户合法性的
private bool Confirm(string user,string password)
{
//
相应的代码
}
//
此方法用来获得的用户对应的所有的
role
用逗号分割的一个字符串
private string UserToRole(string user)
{
//
相应的代码
}
二
基于角色访问授权
这里我们要做的是
,
将客户端保存的身份验证票中
UserData
中保存的表示角色的信息恢复到在服务端表示用户身份的
GenericPrincipal
对象中
(
记住
,
原来的验证过程中
, GenericPrincipal
对象只包含了用户信息
,
没有包含
role
信息
)
一个
Http
请求的过程中
,HttpApplication.AuthenticateRequest
事件表示安全模块已建立用户标识,就是此用户的身份在
web
端已经建立起来
,
在这个事件之后我们就可以获取用户身份信息了
.
在
HttpApplication.ResolveRequestCache
事件之前,
asp.net
开始取得用户请求的页面,建立
HttpHandler
控制点
,
这时就已经要验证用户的权限了
,
所以恢复用户角色的工作只能在
HttpApplication.AuthenticateRequest
事件和
HttpApplication.ResolveRequestCache
事件之间的过程中做
.
我们选择
Application_AuthorizeRequest
事件中做这个工作
,
可以在
global.asax
文件中处理
HttpApplication
的所有的事件
,
代码如下
:
protected void Application_AuthorizeRequest(object sender, System.EventArgs e)
{
HttpApplication App = (HttpApplication) sender;
HttpContext Ctx = App.Context ; //
获取本次
Http
请求相关的
HttpContext
对象
if (Ctx.Request.IsAuthenticated == true) //
验证过的用户才进行
role
的处理
{
FormsIdentity Id = (FormsIdentity)Ctx.User.Identity ;
FormsAuthenticationTicket Ticket = Id.Ticket ; //
取得身份验证票
string[] Roles = Ticket.UserData.Split (',') ; //
将身份验证票中的
role
数据转成字符串数组
Ctx.User = new GenericPrincipal (Id, Roles) ; //
将原有的
Identity
加上角色信息新建一个
GenericPrincipal
表示当前用户
,
这样当前用户就拥有了
role
信息
}
}
访问者同时具有了
user
和
role
信息
,
就可以据此在
web.config
中用
role
来控制用户的访问权限了
.