閱讀692 返回首頁    go 技術社區[雲棲]


FormsAuthenticationTicket基於forms的驗證

FormsAuthenticationTicket基於forms的驗證

一、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文件 
 加入節點,nameCOOKIE名稱,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事件中加入

  原理,將用戶角色信息保存在票據中,通過Global.asax,WEB.CONFIG中的設置,判斷角色的權限 

二、使用Forms驗證存儲用戶自定義信息

    Forms驗證在內部的機製為把用戶數據加密後保存在一個基於cookie的票據FormsAuthenticationTicket中,因為是經過特殊加密的,所以應該來說是比較安全的。而.net除了用這個票據存放自己的信息外,還留了一個地給用戶自由支配,這就是現在要說的UserData

    UserData可以用來存儲string類型的信息,並且也享受Forms驗證提供的加密保護,當我們需要這些信息時,也可以通過簡單的get方法得到,兼顧了安全性和易用性,用來保存一些必須的敏感信息還是很有用的。

下麵來看怎麼使用UserData,然後會給出一個實際使用的例子。

//創建一個新的票據,將客戶ip記入ticketuserdata 
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); 

使用userdata也很簡單,FormsIdentityTicket屬性就提供了對當前票據的訪問,獲得票據後就可以用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空的GenericIdentityroles使票據失效,這樣將強迫用戶重新登錄。為了測試這個方法,可以先把條件改為相等,看效果如何 。

這個方法也有不足之處,具體為:

1.使用同一代理的用戶將擁有同一個ip,這樣就不能防範此類假冒攻擊了

2.如果用戶使用動態ip,則可能造成正常用戶被我們強行銷毀票據。不過總的來說,這個辦法還是比較可行的。

 

最後更新:2017-04-02 06:51:20

  上一篇:go 2相四線,四相五線,四相六線步進電機接線及驅動方法
  下一篇:go magento -- 新會員首次購物免運費的實現思路