ASP.NET安全問題--Froms驗證的具體介紹(上篇)
前言:在ASP.NET中,常用的就是Forms驗證,最重要的原因就是靈活。因為Forms驗證細細的談起來也確實不少,而且我也不想草草的說完了事,那對大家和自己都不負責任的。
系列文章連結:
ASP.NET開發安全問題
ASP.NET安全問題-- 建立安全的Web應用程式
ASP.NET安全問題--ASP.NET安全架構
ASP.NET安全問題--ASP.NET安全架構--如何?.NET安全
ASP.NET安全問題--ASP.NET生命週期中的驗證以及身分識別驗證模組
ASP.NET安全問題--Forms驗證的具體介紹(上篇)
ASP.NET安全問題--Froms驗證的具體介紹(中篇)
ASP.NET安全問題--Forms驗證(後篇)--實戰篇
ASP.NET安全問題--ASP.NET中的授權問題(前篇)
本篇的話題如下:
Forms驗證的工作原理
Forms驗證中的API
Forms驗證的工作原理
我們知道,Forms驗證主要是基於cookie的,說白一點就是:把使用者資訊儲存在cookie中,然後發送到用戶端;再就是解析用戶端的發送了的cookie資訊,進行解析,然後進行驗證。關於cookieless的工作原理和方法,我這裡不贅述,大家可以參看我的另外的一片文章:淺談ASP.NET內部機制(一)。
當匿名使用者請求一個需要驗證後才能訪問的資源和頁面的時候,那麼如果採用了Forms驗證,那麼URL授權模組就會把使用者重新導向到登入頁面。而之前請求的URL就會被儲存起來,等到使用者正確的登入後,就再次轉向之前要請求的頁面。我想這點,大家應該都用過。
下面我們就看看登入的時候發生了什麼,看看登入的具體的流程?也請大家注意我使用的一些術語,因為這些術語再Forms中都有特定的對象,大家之後就可以看到的,很重要。
1.再瀏覽器中有個登入表單,要輸入使用者名稱和密碼等憑證,通過提交給伺服器的ASP.NET網站來審核,檢查憑證是否正確。
2.如果憑證正確,那麼就會再伺服器端就會建立一個"身分識別驗證票據"。身分識別驗證票據中含有了經過加密的使用者資訊。
3.這個票據再伺服器端被寫入cookie中,然後發送到用戶端。
4.然後使用者就被重新導向到他們最初請求的URL中。
註:大家可能會有疑問:最初請求的URL到底儲存在哪裡?不要擔心,現在只要明白上面的流程就OK。
5.上面第4步就是要轉向最初請求的URL,假設最初的請求頁面是Default.aspx,那麼現在就是從登入的頁面Login.aspx轉向到Default.aspx 頁面,此時因為身分識別驗證的票據cookie已經存在於用戶端的瀏覽器中了,此時的轉向Default.aspx頁面時,實際是再次向伺服器端發起了請求,所以正如我們之前所談到的:每個請求都要從ASP.NET管道中一級級的向後傳,要經曆ASP.NET的的生命週期:Application_BeginRequest,Application_AuthenticateRequest.....。(希望大家明白)
但是這次的請求就和第一次我們發起的請求步同了,為什嗎?
第一次我們請求Default.aspx頁面的時候,我們根本就沒有提供任何的表明我們身份的票據,但是這次我們已經登入了,而且我們的瀏覽器中已經有了我們的身分識別驗證的票據的cookie,此時在Application_AuthenticateRequest事件中,Forms驗證模組就擷取表明我們身份cookie,然後就利用cookie中資訊填充Context.User。
驗證模組處理完之後就是授權模組起作用了。其實URL授權模組就會利用我們之前填充在Context.User中的資訊來驗證使用者是否被批准訪問所請求的資源或者頁面。
Forms驗證中的API
實現Forms身分識別驗證之前,我們看看組成Forms驗證的API以及相關的類:
FormsAuthenticationModule:對每個請求進行驗證的HTTP模組
FormsAuthentication:包含在Forms驗證中我們常用的方法和屬性(很重要的)
FormsIdentity:Forms驗證標識。
FormsAuthenticationTicket:身分識別驗證的票據,對使用者的資訊進行加密後的產物,我們一般把它寫如cookie中,之前我們談過了的。
上面的類在System.Web.Security下。
下面我們來一一介紹.
FormsAuthenticationModule
它是一個實現了IHttpModule介面的類。它可以用來處理每個請求的Application_AuthenticateRequest事件。如果發送了的請求中已經包含了cookie資訊,那麼這個模組就對cookie資訊進行解密和解析,然後構造一個GenericPrincipal的類執行個體填充Context.User,並且也建立一個FormsIdentity的執行個體。
注意:當我們在web.config中配置了Forms驗證後,那麼我們在Application_AuthenticateRequest事件寫的代碼要是和Forms相關的API。上篇文章談過了。
FormsAuthentication類
這個類很重要。
還有一點注意的就是:因為FormsAuthentication和FormsAuthenticationModule名稱很相似,很容易混淆。
它們之前的區別在於,FormsAuthenticationModule是一個HTTP模組;而FormsAuthenticate是一個類,它有很多的方法和屬性。更加直白的說就是:它們之前沒有什麼關聯,只是在Application_AuthenticateRequest事件中我們常常要調用FormsAuthenticate類的一些方法和屬性。而且FormsAuthenticate的很多方法都是靜態方法,我們不會建立FormsAuthenticate類的執行個體。
還有一點要特別注意的就是FormsAuthenticate的Authenticate方法。
我們之前說過了,我們一般是在登入表單中提交使用者資訊,然後伺服器端驗證提交的資訊,我們在伺服器端常常是去資料庫中檢查這些資訊的正確性,但是去資料庫或者其他的資料存放區(如檔案,活動目錄)中去檢查只是一種情況。
還有另外的情況。不知道大家是否記得web.config 中的一個配置的節點:
<authentication mode="Forms">
<forms>
<credentials>
<user name="xiaoyang" password="xiaoyang"/>
<user name="panyan" password="panyan"/>
</credentials>
</forms>
</authentication>
如果我們在設定檔配置了上述的資訊,那麼我們就可以用Authenticate方法來檢查提供了使用者資訊(使用者名稱和密碼)是否正確,如果我們沒有在web.config配置使用者的資訊,也就是說我們是把資訊儲存在資料庫等其他的地方,那麼我們就不能Authenticate這個方法。當然我們很少用Authenticate這個方法,因為我們不可能把所有使用者資訊寫入程式碼到設定檔中,但是還是要清楚這個方法。
另外我簡單的介紹一些常用的方法,具體的使用我以後會講述。
在FormsAuthenticate中使用頻繁的是RedirectFromLoginPage方法。每當驗證了使用者的憑證後就會使用到這個方法,也就是我們之前說過的:跳轉到我們最初請求的頁面。
這個方法就這麼簡單的一"跳",但是其實在內部做了很多的事情:
1.為使用者建立一個身分識別驗證的票據
2.對身分識別驗證的票據進行加密
3.建立一個cookie,把加密的票據儲存在cookie中
4.向HTTP響應添加cookie,並且發送給用戶端。
5.跳轉,並且把使用者重新導向到最初請求的頁面
另外FormsAuthenticate類還有很多的其他方法和屬性:
FormsAuthenticate中涉及到用戶端儲存cookie的兩個屬性就是:
FormsCookieName:擷取或者設設定cookie的名稱
FormsCookiePath:擷取或者設定cookie的url路徑
其中FormsCookiePath屬性有一點要注意:大多數的瀏覽器會在判斷cookie是否要和請求一起發送時,用到cookie路徑。(我們一般在設定檔配置path="/"),如果我們配置的path不是"/",那麼這個cookie就不會和請求發送到伺服器端.
FormsAuthenticate中和cookie操作相關的方法有:
Decrypt:提取身分識別驗證cookie的加密資訊,建立FormsAuthenticationTicket,也就是解密。
Encrypt:加密。從FormsAuthenticationTicket中擷取資訊,並且加密。以備我們之後把加密的資訊寫入cookie
GetAuthCookie:建立身分識別驗證cookie,但是並不把它立即添加到HTTP響應中
SetAuthCookie:建立身分識別驗證cookie,並且把它添加到Response.Cookie中。
RenewTicketIfOld:重新整理身分識別驗證cookie的生命週期
GetRedirectUrl:把使用者重新導向到他們最初請求的頁面。
SignOut:使得當前的身分識別驗證cookie到期。我們常用的登出功能。
FormsIdentity
大家現在應該知道什麼是標識 Identity,它包含了使用者名稱和ID標識資訊,可以參看我前面的文章。
FormsAuthenticationTicket 票據
通過上面的講解,大家已經對它不陌生了,FormsAuthenticationTicket實際上就包含使用者資訊的一個類的執行個體。
注意:FormsAuthenticationTicket和cookie之間的區別:
cookie其實就是一個載體,容器,它包含了加密後的FormsAuthenticationTicket。
FormsAuthenticationTicket類的UserName屬性就是使用者的使用者名稱,我們可以根據這個屬性識別不同的使用者。
由於身分識別驗證是基於cookie的,所以要考慮到cookie的到期的問題。比如我們在登入時有個"記住我"的checkbox,如果勾上,那麼就建立了一個永不到期的cookie,處於安全,我不提倡這樣。
所以在FormsAuthenticationTicket也提供了關於設定cookie屬性:
Expiration:擷取一個表示cookie期滿的DateTime對象
Expired:判斷cookie是否到期
IsPersistent:是否在使用者關閉瀏覽器後繼續儲存cookie
IssueDate:返回最初設定cookie的時間
還有就是CookiePath:設定cookie的儲存路徑,前面談論過了,一般設定為"/"。
另外FormsAuthenticationTicket身分識別驗證票據目的是識別使用者。同時,我們也可以利用FormsAuthenticationTicket的UserData屬性添加額外的資訊,如角色等,然後這額外的資訊就可以儲存在cookie中。
今天就談這裡。大家先有個總體的認識,具體的代碼部分,我們後面談。謝謝各位!!!