• FormsAuthenticationTicket学习笔记


    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "username", DateTime.Now, DateTime.Now.AddDays(365),
                 true, string.Format("{0}:{1}", "username", "password"), FormsAuthentication.FormsCookiePath);
                //这边的 string.Format("{0}:{1}", "username", "password"),也可以改为任何值,如密码或IP
                string ticString = FormsAuthentication.Encrypt(ticket);
                //将加密后的票据保存为cookie 
                HttpCookie coo = new HttpCookie(FormsAuthentication.FormsCookieName, ticString);
                //这里的IsPersistent不会自己判断,需要手工判断,但FormsAuthenticationTicket的expiration的值是有过期性的,无论cookie的Expires设置多久,只要expiration到期,即使cookie存在用户验证也将失败
                if (ticket.IsPersistent)
                {
                    coo.Expires = ticket.Expiration;
                }
                //使用加入了userdata的新cookie 
                Response.Cookies.Add(coo);
                //FormsAuthentication.SetAuthCookie("username", true);//这种是快速写法,用了这种写法就可以不用自己建ticket票据,也无法使用UserData等参数了
    
    
                //FormsAuthentication.SignOut//用来清除这个Cookie标记//FormsAuthentication.RedirectFromLoginPage(userID, createPersistentCookie);
    
            //    <authentication mode="Forms">
            //    <forms name=".MyCookie" loginUrl="Login.aspx" protection="All" timeout="60"/>
            //    </authentication>

    总结:

    1.FormsAuthentication一共有两种生成并记录票具的方法:

      一种是自己new FormsAuthenticationTicket,然后自己保存到Cookie中,ticket的 IsPersistent属性仅起到标识的作用,并不会去修改Cookies的到期时间,需要人工自己判断后设置cookies的到期时间(if (ticket.IsPersistent){coo.Expires = ticket.Expiration; })。

      另一种是使用FormsAuthentication.SetAuthCookie("username",IsPersistent: false);来快捷生成ticket,这种方法系统会自动新建一个cookies来保存ticket,并根据IsPersistent是否为true, 以及webconfig中的timeout来确定cookies的到期时间。

    2.如果使用第一种方法,无论自己把cookies的时间设置为多久,只要ticket.Expiration到期了,及时cookies还存在,用户验证依然会失败。

    3.UserData是个好东西,可以用来存储IP地址,用于判断访问者是否是恶意截取cookies。

    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)
     
      如果需要存储角色,采用:
     FormsAuthenticationTicket authTicket = new
     FormsAuthenticationTicket(
      1, // 版本号。
      txtUserName.Text, // 与身份验证票关联的用户名。
      DateTime.Now, // Cookie 的发出时间。
      DateTime.Now.AddMinutes(20),// Cookie 的到期日期。
      false, // 如果 Cookie 是持久的,为 true;否则为 false。
      roles ); // 将存储在 Cookie 中的用户定义数据。
      roles是一个角色字符串数组
      string encryptedTicket = FormsAuthentication.Encrypt(authTicket); //加密
     
      存入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>
      <authorization>
      <allow roles="admin"/>
      <deny users="*"/>
      </authorization>
      </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中的设置,判断角色的权限

  • 相关阅读:
    前端面试
    (知乎)我想问一下PHP的学习路线图
    sublime text3如何安装bootstrap的插件
    php项目开发经验-2个月学习php经历
    基于链接的基本排序算法原理
    焦大:特征权重的处理与最终排名(中)
    焦大:特征权重的处理与最终排名(下)
    如何分析和监测竞争对手网站的seo数据
    没收录的页面是否会传递权重
    想学习SEO可以看哪些书籍
  • 原文地址:https://www.cnblogs.com/hnsongbiao/p/4462093.html
Copyright © 2020-2023  润新知