FormsAuthenticationTicket对象

1.使用Forms验证存储用户自定义信息

Forms验证在内部的机制为把用户数据加密后保存在一个基于cookie的票据FormsAuthenticationTicket中,因为是经过特殊加密的,所以应该来说是比较安全的。

而.net除了用这个票据存放自己的信息外,还留了一个地给用户自由支配,这就是现在要说的UserData。

UserData可以用来存储string类型的信息,并且也享受Forms验证提供的加密保护,当我们需要这些信息时,也可以通过简单的get方法得到,兼顾了安全性和易用性,用来保存一些必须的敏感信息还是很有用的。

下面来看怎么使用UserData,然后会给出一个实际使用的例子。

{
        //创建一个新的票据,将客户ip记入ticket的userdata
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName.Text, DateTime.Now, DateTime.Now.AddMinutes(30), false, Request.UserHostAddress);
        //将票据加密
        string authTicket = FormsAuthentication.Encrypt(ticket);
        //将加密后的票据保存为cookie
        HttpCookie coo = new HttpCookie(FormsAuthentication.FormsCookieName, authTicket);
        //使用加入了userdata的新cookie
        Response.Cookies.Add(coo);
}


下面是FormsAuthenticationTicket构造函数的重载之一的方法签名

public FormsAuthenticationTicket(int version,string name,DateTime issueDate,DateTime expiration,bool isPersistent,string userData);

参数解释:
version          版本号。
name            与身份验证票关联的用户名。
issueDate    Cookie 的发出时间。
expiration     Cookie 的到期日期。
isPersistent  如果 Cookie 是持久的,为 true;否则为 false。
userData       将存储在 Cookie 中的用户定义数据

使用userdata也很简单,FormsIdentity的Ticket属性就提供了对当前票据的访问,获得票据后就可以用UserData属性访问保存的信息,当然是经过解密的。
((System.Web.Security.FormsIdentity)this.Context.User.Identity).Ticket.UserData

下面是一个具体的应用。

由于Forms验证是通过cookie来进行的,它需要传递一个票据来进行工作。虽然票据是加密的,里面的内容不可见,但这并不能阻止别人用一个假冒的身份使用票据(就像我们可以拿别人的钥匙去开别人的锁),比较常见的就是不同ip的用户在不安全通道截获了这个票据,然后使用它进行一些安全范围外的活动。

解决这个问题的办法之一就是使用SSL来传递信息。

但是如果不能使用SSL呢?我们可以判断ip和票据是否匹配,如果发出请求的ip是初次产生票据的ip,则没有问题,否则就销毁这个票据。

为此,我们需要在一开始处理登录时将用户的ip保存起来,这样就可以在以后的请求中随时验证后继请求的ip是否和初始ip相同。保存这个敏感ip的最佳场所当然是UserData啦,而验证的时机则是在AuthenticateRequest事件发生时,即Global.aspx.cs中定义的处理此事件的Application_AuthenticateRequest方法中。

上面的示例实际上已经是把用户ip保存到了UserData中,下面是验证的过程。

{
        if (this.Request.IsAuthenticated)
        {
            if (((System.Web.Security.FormsIdentity)this.Context.User.Identity).Ticket.UserData != this.Request.UserHostAddress)
            {
                System.Security.Principal.GenericIdentity gi = new System.Security.Principal.GenericIdentity("", "");
                string[] rolesi = { };
                System.Security.Principal.GenericPrincipal gpi = new System.Security.Principal.GenericPrincipal(gi, rolesi);
                this.Context.User = gpi;
            }
        }
}

通过给GenericPrincipal空的GenericIdentity和roles使票据失效,这样将强迫用户重新登录。为了测试这个方法,可以先把条件改为相等,看效果如何 :)

这个方法也有不足之处,具体为:

1.使用同一代理的用户将拥有同一个ip,这样就不能防范此类假冒攻击了

2.如果用户使用动态ip,则可能造成正常用户被我们强行销毁票据。不过总的来说,这个办法还是比较可行的。


FormsAuthenticationTicket基于forms的验证

构建基于forms的验证机制过程如下:

  1.  设置IIS为可匿名访问和asp.net web.config中设置为form验证
  2.  检索数据存储验证用户,并检索角色(如果不是基于角色可不用)
  3.  使用FormsAuthenticationTicket创建一个Cookie并回发到客户端,并存储角色到票据中,如: 
 FormsAuthentication.SetAuthCookie(Username,true | false)

  cookies保存时间:

HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName].Expires=DateTime.Now.AddDays(1)

  如果需要存储角色,采用:

{
        //创建一个新的票据,roles是一个角色字符串数组,将存储在 Cookie 中的用户定义数据。 上边代码中是将客户ip记入ticket的userdata ,所以写的是Request.UserHostAddress
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName.Text, DateTime.Now, DateTime.Now.AddMinutes(30), false, Roles);
        //将票据加密
        string encryptedTicket = FormsAuthentication.Encrypt(ticket);

        //存入Cookie
        HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        Response.Cookies.Add(authCookie);
}

  4.    在Application_AuthenticateRequest事件中处理程序中(Global.asax)中,使用 票据创建IPrincipal对象并存在HttpContext.User中
  代码:

{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);//解密
    string[] roles = authTicket.UserData.Split(new char[] { ';' });//根据存入时的格式分解,;或|....
    Context.User = new GenericPrincipal(Context.User.Identity, Roles);//存到HttpContext.User中
}

 判断某个角色验证

 HttpContext.Current.User.IsInRole(roles)

 具体实现
 Web.config文件
 加入节点,name为COOKIE名称,loginUrl为没有通过验证跳转的地址 

  <system.web>
    <authentication mode="Forms">
        <forms name="Hstear" loginUrl="login.aspx" protection="All" path="/" timeout="40"/>
       
    </authentication>     
  </system.web>

 设置目录访问 path为目录名,roles为票据中的角色名
 发现网上的都说要单独一个WEB.CONFIG文件放在目录中,但实际在根目录中设置即可,单个文件也一样

  <location path="Admin">
    <system.web>
      <authentication>
          <allow roles="admin"/>
          <deny users="*"/>
        
      </authentication>
    </system.web>
  </location>

 Global.asax文件
 Application_AuthenticateRequest事件中加入


    protected void Application_AuthenticateRequest(Object sender, EventArgs e)   {  
        string cookieName = FormsAuthentication.FormsCookieName;  
        HttpCookie authCookie = Context.Request.Cookies[cookieName];  
        FormsAuthenticationTicket authTicket = null;  
        try  {   
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);  
        }  
        catch(Exception ex)  {   return;  }    
        string[] roles = authTicket.UserData.Split(new char[]{','});//如果存取多个角色,我们把它分解
        FormsIdentity id = new FormsIdentity( authTicket );    
        GenericPrincipal principal = new GenericPrincipal(id, roles);  Context.User =principal; //存到HttpContext.User中     
    } 

 原理,将用户角色信息保存在票据中,通过Global.asax,WEB.CONFIG中的设置,判断角色的权限

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值