2004-7-24+ Forms验证初步

关于Forms验证的最好的教程,我觉得是microsoft press 出的黑皮书《microsoft.net 程序设计技术内幕》里的关于这一部分的讲解,此书的中文版由清华大学出版社出版。大家方便找到的话,可以看看。
窗体验证是asp.net最酷的新特性之一。简单说,窗体验证是一种安全机制,它通过要求用户在web窗体中输入凭据(通常是用户名和密码)来验证用户身份。您可以在web.config中指定登录页面并告诉asp.net登录页面保护什么资源。当用户第一次试图访问被保护资源时,asp.net会把用户重新定向到您的登录页面。如果登陆成功,asp.net会以cookie的形式发给用户一个验证票据,并把用户重定向到最初请求的页面。这张票据使得用户不必重复登录,就可以多次访问您站点上的被保护内容。您控制这张票据的生存期,所以由您决定登录适用于多长时间。
上面这段话明白吗?我们可以想以前asp的时候,要保护的页面都会有对cookie(或session)的判断,根据cookie的值来判断用户是否有访问这个页的权力。而具体做的时候,都是先要求用户登陆,成功后就把用户信息保存在cookie里面,然后用户就可以访问受保护的页。而现在asp.net提供了一种更加方便的功能来替你完成这些工作,就是上面说的Forms验证。就像分页,以前asp不也替你完成了嘛,可是到了asp.net这里,就得自己动手了……
过程是先建一个文件夹,然后把要保护的页面放进去,接着设置一下web,config,这样就完成了保护。如果你要访问这个文件夹,就会被强制转到预先设定的登录页面,你填上正确的用户名和密码,提交,系统验证后,就把你的登陆信息写到cookie里面,这样你再去访问那个文件夹,就可以进去了,因为你的登陆凭证已经保存到cookie里面了,系统检查后,知道你不是坏人,于是就……这个过程还是和以前asp时的过程差不多。
下面是具体的操作,先要建一个asp.net应用程序,这里面至少要有一个登录用的页面,然后修改你的根目录下的web.config,把验证那一块改成Forms验证模式。
<authentication mode="Forms" >
<forms loginUrl="login.aspx">
</forms>
</authentication>

注意里面有一个forms节,定义了登录页面的位置,如果不指定,则默认是根目录下的login.aspx,还有,里面是区分大小写的。
通过这个设置,系统就知道这个asp.net应用程序使用Forms验证。
接下来在要保护的文件夹里放一个web.config,要注意的是,这个子文件夹里的web.config的实际内容不能像根目录下的那个一样多,否则就会出现“配置错误”,提示“在应用程序级别以外使用注册为 allowDefinition='MachineToApplication' 的节是错误的。导致该错误的原因可能是在 IIS 中没有将虚拟目录作为应用程序进行配置。”具体应该怎么做我也不清楚,总之这个web.config只要有下面的内容就ok了
<configuration>
<system.web>
<authorization>
<deny users="?"></deny>
</authorization>
</system.web>
</configuration>

这是一个授权节,此节设置应用程序的授权策略。可以允许(allow)或拒绝(deny)不同的用户或角色访问应用程序资源。通配符: "*" 表示任何人,"?" 表示匿名(未经身份验证的)用户。看我们上面的设置知道,这样配置就是拒绝未经身份验证的用户访问。
然后可以试试访问那个受保护的文件夹里的页面了,嘿嘿,是不是立刻就被转到login.aspx了?这就是Forms验证的威力了,你必须要在这里正确登陆,然后才可以访问受保护的资源。
接下来自然就是登陆的问题了。
想想在asp的时代,我们的登陆事件是这样的:
sql="select name,password from yourtable where name="&name&" password="&password
set rs=con.execute(sql)
if not rs.eof
cookie("login")="ok"
end if

上面是基本的过程了,注意这个做法是极不安全的,这里只是一个示例,而在Forms验证时的过程也差不多,即
if(1.输入的用户名和密码合法) then
2.给用户设定登陆凭证
end if

先看第一步,怎样检查输入的用户名和密码合法,这里有两个办法,如果你是把用户名和密码存在数据库里面,那就用以前的办法来解决,比如是islogin(string name,string password)方法,如果你输入正确的用户名和密码的话,这个方法就返回true。这个办法适用于很多用户的时候。 如果你的用户数量很少,那就可以考虑第二种办法,即把用户和密码放到web.config里。办法就是在根目录下的web.config文件中加入一个credentials节,这个是包含在forms节里面的
<authentication mode="Forms" >
<forms loginUrl="login.aspx">
<credentials passwordFormat="Clear">
<user name="notus" password="wei"/>
</credentials>

</forms>
</authentication>
在这里设置后,程序中的判断是用System.Web.Security的FormsAuthentication类的一个方法System.Web.Security.FormsAuthentication.Authenticate(string name,string password),这个就是用来根据web.config文件中的credentials节指定的用户名和密码来进行合法性判断,如果你输入正确的话,这个方法就返回true。
验证完后,就进入第二个步骤给用户设定登陆凭证,这里也是用到System.Web.Security的FormsAuthentication类的一个方法
System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string,bool)这个方法接受两个参数,第一个string是用语cookie身份验证的用户名称,一般就用用户名,第二个是bool值,用于指定此cookie是临时的,还是永久性的,如果这里用false,那就是临时性的。临时性的cookie的生存期可以在web.config的forms节中指定
<forms loginUrl="login.aspx" timeout="10">
这里是把超时时间设为10分钟。而永久性cookie的生存期是50年,并且设定后就不可以更改,一般如果选择永久性的cookie的话,可以通过编程的办法来改变这个值,毕竟50年实在是太长了。
这个方法除了设定用户登陆凭证外,在最后还会把用户重定向到最初请求的页面,即当你没有登录而直接进入受保护的文件夹时想去的那个页面。如一开始直接进入登录页面,则最后会转向根目录下的default.aspx。
下面是具体的代码演示,这段代码是单击登陆页面的提交按钮后执行的,boxid和boxpd分别是输入用户名和密码的textbox
第一种,用户资料保存于数据库时
private void butlogin_Click(object sender, System.EventArgs e)
{
   if(islogin(boxid.Text,boxpd.Text))
     FormsAuthentication.RedirectFromLoginPage(boxid.Text,false);
   else
     Response.Write("error");
}

第二种,用户资料保存于web.config时
private void butlogin_Click(object sender, System.EventArgs e)
{
   if(FormsAuthentication.Authenticate(boxid.Text,boxpd.Text))
     FormsAuthentication.RedirectFromLoginPage(boxid.Text,false);
   else
     Response.Write("error");
}

这就是验证的基本过程。
而如果想要注销登陆,则用System.Web.Security的FormsAuthentication类的SignOut()方法
private void butquit_Click(object sender, System.EventArgs e)
{
   FormsAuthentication.SignOut();
}

它返回一个Set-Cookie头,将Cookie的值设置为一个空字符串,并将Cookie的到器日期设置为一个过去的日期,从而有效销毁验证cookie。
而在实际情况下,您可能更愿意在顶层web.config文件中完成所有的url授权,而不是把它们分在各自目录下的web,config文件中。asp.net也支持这种做法。下面这个web,config文件,放在应用程序根目录下,它启用窗体验证并指定其他的一些设置。假设您要保护的文件夹名为protd。
<configuration>
<system.web>
<authentication mode="Forms" >
<forms loginUrl="login.aspx">
<credentials passwordFormat="Clear">
<user name="notus" password="wei"/>
</credentials>
</forms>
</authentication>
</system.web>
<location path="protd">
<system.web>
<authorization>
<deny users="?"></deny>
</authorization>
</system.web>
</location>
</configuration>

注意它的层次结构,应该有两个<system.web>节。完成这个后,就可以把protd文件夹下的那个web.config删掉,然后看看效果如何。
基本的知识就这么多了,其实Forms验证还有很多内容,比如怎样以编程的方式改变永久性cookie的生存期,怎么使用基于角色的验证等,这些大家找相关资料研究研究吧。当然还是推荐上面说到的那本书,以前关于Forms验证的也看了不少资料,但总是不明白,结果昨天一看那本书的讲解,就豁然开朗了。
最后再给出我常用的一个islogin()代码。希望可以对初学者有些帮助。
public bool islogin(string name,string password)
{
   bool isok=false;
   string errmsg="ok";
   StringBuilder sbsel=new StringBuilder();
   sbsel.Append("select name,password from youtable where name='");
   sbsel.Append(name);
   sbsel.Append("'");
   try
   {
      cmd=new OleDbCommand(sbsel.ToString(),conn);
      conn.Open();
      OleDbDataReader dr=cmd.ExecuteReader(CommandBehavior.SingleRow);
      if(dr.Read())
      {
         if(dr["password"].ToString()==password)
         isok=true;
      }
      errmsg="login is ok";
   }
   catch(OleDbException ex)
   {
      errmsg=ex.Message;
   }
   finally
   {
      conn.Close();
   }
   return isok;
}

posted on 2006-06-29 09:31  Notus|南色的风  阅读(312)  评论(0编辑  收藏  举报