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中的設置,判斷角色的權限


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM