ASP.NET 深入探讨 Forms 验证

来源:互联网 发布:喵喵折 mac 编辑:程序博客网 时间:2024/06/10 02:46
1.受Forms验证保护的对象
Forms验证只保护asp.net文件。他保护注册到asp.net的aspx文件、asmx文件及其他文件,但是不保护不属于asp.net的文件-如,文件扩展名为.htm或.html的文件。因为asp.net从来看不到对没有注册到它的文件的请求。
2.web.config的location节
使用location节可以很容易的在根目录下的web.config设置整个应用程序的保护范围。下面是一个示例。
<location path="secret"><system.web><authorization><allow roles="coder,manager"></allow><deny users="*"/></authorization></system.web></location><location path="secret/manage.aspx"><system.web><authorization><allow roles="manager"></allow><deny users="*"/></authorization></system.web></location><location path="coo.aspx"><system.web><authorization><allow roles="coder"></allow><deny users="*"></deny></authorization></system.web></location>

使用location节来指定了三个不同的保护措施,其中secret/manage.aspx是在secret的保护级别里又加了一层。
3.自由设定验证cookie的超时时间。
在FormsAuthentication.SetAuthCookie(string,bool)方法中,有个参数可以设定验证cookie是临时的还是永久的,如是false,就是临时,时间按web,config中的设定时间来算。如果true,那就是永久的,默认值为50年(……),但是我们可以通过编程的方式来改变这个数字,这就实现了很多地方有“选择cookie保留时间”的功能。
//给用户添加验证凭证FormsAuthentication.SetAuthCookie(username.Text,true);//获取验证cookie,FormsAuthentication.FormsCookieName的值就是cookie的name默认是.ASPXAUTH,可以在web.config更改HttpCookie coo=Response.Cookies[FormsAuthentication.FormsCookieName];//根据用户对RadioButtonList的选择改变cookie的超时时间switch(timeout.SelectedValue){   case "1" :   coo.Expires=DateTime.Now+new TimeSpan(0,0,1,0);   break;   case "10" :   coo.Expires=DateTime.Now+new TimeSpan(0,0,10,0);   break;   case "60" :   coo.Expires=DateTime.Now+new TimeSpan(0,0,60,0);   break;   default :   coo.Expires=DateTime.Now+new TimeSpan(0,0,1,0);   break;}

4.获取用户信息
这个问题就是,通过Forms验证后,怎么才能得到用户名。其实也简单,通过Page的User属性来完成这个任务。User属性返回一个IPrincipal对象,然后IPrincipal有个Identity属性,可以获取当前用户的标识。
再说一下这个User,是为当前 HTTP 请求获取或设置安全信息。HttpContext.User 属性提供对 IPrincipal接口的属性和方法的编程访问。
IPrincipal对象,表示代码为其运行的用户的安全上下文,包括用户的标识和任何它们所属的角色。
//IPrincipal接口的属性IdentityResponse.Output.Write(Page.User.Identity.Name+"<br>");Response.Output.Write(Page.User.Identity.AuthenticationType+"<br>");Response.Output.Write(Page.User.Identity.IsAuthenticated+"<br>");//IPrincipal接口的方法IsInRoleResponse.Write(Page.User.IsInRole("manager"));

5.使用角色。
上面演示location节时用的验证方法都是基于角色的验证。角色这个词可以参照mssql里的角色,就是一系列不同的权限,比如只有角色是manager的人才可以查看secret/manage.aspx。
具体用法就是在定义用户的同时添加一个role字段,这个字段为该用户分配角色。然后在进行验证的时候通过Global.asax的Application_AuthenticateRequest事件在用户验证时将该用户的角色添加到用户凭证中,最后web.config根据用户的角色判断该用户是否有权力查看相应的页面。
注意我这里说的是把用户资料存在数据库中的情况。下面的代码放在Global.asax.cs文件中。
protected void Application_AuthenticateRequest(Object sender, EventArgs e){   //获得当前HttpApplication,定义 ASP.NET 应用程序中的所有应用程序对象通用的方法、属性和事件。   HttpApplication app=(HttpApplication)sender;   //检查用户是否通过了验证及验证类型是否为forms验证   if(app.Request.IsAuthenticated && app.User.Identity is FormsIdentity)   {      //将当前用户的身份转成formsidentity      FormsIdentity fid=(FormsIdentity)app.User.Identity;      //获取该用户的角色      string role=getRole(fid.Name);      //通过设置GenericPrincipal,来将roles添加到当前用户。GenericPrincipal:此类表示当前用户的角色。       if(role!=null)         app.Context.User=new GenericPrincipal(fid,new string[] {role});   }}//获取用户的角色private string getRole(string name){   string strconn=ConfigurationSettings.AppSettings[0];   SqlConnection conn=new SqlConnection(strconn);   string sql="select role from users where username= @username";   SqlCommand cmd=new SqlCommand(sql,conn);   SqlParameter uname=new SqlParameter("@username",SqlDbType.VarChar,50);   uname.Value=name;   cmd.Parameters.Add(uname);   try   {      conn.Open();      object role=cmd.ExecuteScalar();      if(role is DBNull)      return null;      return (string)role;   }   catch(SqlException)   {      return null;   }   finally   {      conn.Close();   }}

比如说username:Notus/password:wei/role:coder。该用户在登陆时对其进行Forms验证,如通过,则给其设定验证凭据,同时Application_AuthenticateRequest事件启动,在该凭据内加入用户的角色信息,在这里为coder。这样用户可以访问coo.aspx,因其角色为coder,也可以访问secret中的文件,但是不可以访问secret/manage.aspx,因为按web.config的设定,只有角色为manager的才可以访问该文件。
6.用户合法性验证
下面是我常用的代码,顺便贴出来。
public bool check(string uid,string pwd){   string strconn=ConfigurationSettings.AppSettings[0];   SqlConnection conn=new SqlConnection(strconn);   string sql="select password from users where username=@username";   SqlCommand cmd=new SqlCommand(sql,conn);   SqlParameter uname=new SqlParameter("@username",SqlDbType.VarChar,50);   uname.Value=uid;   cmd.Parameters.Add(uname);   try   {      conn.Open();      object password=cmd.ExecuteScalar();      if(password is DBNull)         return false;      if((string)password!=pwd)         return false;      return true;   }   catch(SqlException ex)   {      return false;   }   finally   {      conn.Close();   }}