ASP.net的身份驗(yàn)證方式FORMS
Asp.net的身份驗(yàn)證有有三種,分別是"Windows | Forms | Passport",其中又以Forms驗(yàn)證用的最多,也最靈活。
Forms 驗(yàn)證方式對基于用戶的驗(yàn)證授權(quán)提供了很好的支持,可以通過一個(gè)登錄頁面驗(yàn)證用戶的身份,將此用戶的身份發(fā)回到客戶端的Cookie,之后此用戶再訪問這個(gè) web應(yīng)用就會連同這個(gè)身份Cookie一起發(fā)送到服務(wù)端。服務(wù)端上的授權(quán)設(shè)置就可以根據(jù)不同目錄對不同用戶的訪問授權(quán)進(jìn)行控制了。
問題來了,在實(shí)際是用中我們往往需要的是基于角色,或者說基于用戶組的驗(yàn)證和授權(quán)。對一個(gè)網(wǎng)站來說,一般的驗(yàn)證授權(quán)的模式應(yīng)該是這樣的:根據(jù)實(shí)際需 求把用戶分成不同的身份,就是角色,或者說是用戶組,驗(yàn)證過程不但要驗(yàn)證這個(gè)用戶本身的身份,還要驗(yàn)證它是屬于哪個(gè)角色的。
而訪問授權(quán)是根據(jù)角色來設(shè)置的,某些角色可以訪問哪些資源,不可以訪問哪些資源等等。要是基于用戶來授權(quán)訪問將會是個(gè)很不實(shí)際的做法,用戶有很多,還可能隨時(shí)的增減,不可能在配置文 件中隨時(shí)的為不斷增加的新用戶去增加訪問授權(quán)的。
下面大概的看一下Forms的過程。
Forms身份驗(yàn)證基本原理:
一 身份驗(yàn)證
要采用Forms身份驗(yàn)證,先要在應(yīng)用程序根目錄中的Web.config中做相應(yīng)的設(shè)置:
- <authentication mode="forms">
- <forms name=".ASPXAUTH " slidingExpiration="true" loginUrl="/login.aspx" timeout="30" path= "/" domain=".abc.com">
- </forms>
</authentication>其中<authentication mode= "forms"> 表示本應(yīng)用程序采用Forms驗(yàn)證方式。
1. <forms>標(biāo)簽中的name表示指定要用于身份驗(yàn)證的 HTTP Cookie。
默認(rèn)情況下,name 的值是 .ASPXAUTH。采用此種方式驗(yàn)證用戶后,以此用戶的信息建立一個(gè)FormsAuthenticationTicket類型的身份驗(yàn)證票,再加密序列 化為一個(gè)字符串,最后將這個(gè)字符串寫到客戶端的name指定名字的Cookie中.一旦這個(gè)Cookie寫到客戶端后,此用戶再次訪問這個(gè)web應(yīng)用時(shí)會 將連同Cookie一起發(fā)送到服務(wù)端,服務(wù)端將會知道此用戶是已經(jīng)驗(yàn)證過的.
再看一下身份驗(yàn)證票都包含哪些信息呢,我們看一下FormsAuthenticationTicket類:
CookiePath: 返回發(fā)出 Cookie 的路徑。注意,窗體的路徑設(shè)置為 /。由于窗體區(qū)分大小寫,這是為了防止站點(diǎn)中的 URL 的大小寫不一致而采取的一種保護(hù)措施。這在刷新 Cookie 時(shí)使用
Expiration: 獲取 Cookie 過期的日期/時(shí)間。
IsPersistent: 如果已發(fā)出持久的 Cookie,則返回 true。否則,身份驗(yàn)證 Cookie 將限制在瀏覽器生命周期范圍內(nèi)。
IssueDate: 獲取最初發(fā)出 Cookie 的日期/時(shí)間。
Name: 獲取與身份驗(yàn)證 Cookie 關(guān)聯(lián)的用戶名。
UserData :獲取存儲在 Cookie 中的應(yīng)用程序定義字符串。
Version: 返回字節(jié)版本號供將來使用。
2. <forms>標(biāo)簽中的loginUrl指定如果沒有找到任何有效的身份驗(yàn)證 Cookie,為登錄將請求重定向到的URL。
默認(rèn)值為 default.aspx。loginUrl指定的頁面就是用來驗(yàn)證用戶身份的,一般此頁面提供用戶輸入用戶名和密碼,用戶提交后由程序來根據(jù)自己的需要 來驗(yàn)證用戶的合法性(大多情況是將用戶輸入信息同數(shù)據(jù)庫中的用戶表進(jìn)行比較),如果驗(yàn)證用戶有效,則生成同此用戶對應(yīng)的身份驗(yàn)證票,寫到客戶端的 Cookie,最后將瀏覽器重定向到用戶初試請求的頁面.一般是用FormsAuthentication.RedirectFromLoginPage 方法來完成生成身份驗(yàn)證票,寫回客戶端,瀏覽器重定向等一系列的動作.
- public static void RedirectFromLoginPage( string userName, bool createPersistentCookie, string strCookiePath );
其中:
userName: 就是此用戶的標(biāo)示,用來標(biāo)志此用戶的唯一標(biāo)示,不一定要映射到用戶賬戶名稱.
createPersistentCookie: 標(biāo)示是否發(fā)出持久的 Cookie。
若不是持久Cookie,Cookie的有效期Expiration屬性有當(dāng)前時(shí)間加上web.config中timeout的時(shí)間,每次請求頁面時(shí),在 驗(yàn)證身份過程中,會判斷是否過了有效期的一半,要是的話更新一次cookie的有效期;若是持久cookie,Expiration屬性無意義,這時(shí)身份 驗(yàn)證票的有效期有cookie的Expires決定,RedirectFromLoginPage方法給Expires屬性設(shè)定的是50年有效期。
strCookiePath: 標(biāo)示將生成的Cookie的寫到客戶端的路徑,身份驗(yàn)證票中保存這個(gè)路徑是在刷新身份驗(yàn)證票Cookie時(shí)使用(這也是生成Cookie的Path),若沒有strCookiePath 參數(shù),則使用web.config中 path屬性的設(shè)置。
這里可以看到,此方法參數(shù)只有三個(gè),而身份驗(yàn)證票的屬性有七個(gè),不足的四個(gè)參數(shù)是這么來的:
IssueDate: Cookie發(fā)出時(shí)間由當(dāng)前時(shí)間得出,
Expiration:過期時(shí)間由當(dāng)前時(shí)間和下面要說的<forms>標(biāo)簽中timeout參數(shù)算出。此參數(shù)對非持久性cookie有意義。
UserData: 這個(gè)屬性可以用應(yīng)用程序?qū)懭胍恍┯脩舳x的數(shù)據(jù),此方法沒有用到這個(gè)屬性,只是簡單的將此屬性置為空字符串,請注意此屬性,在后面我們將要使用到這個(gè)屬性。
Version: 版本號由系統(tǒng)自動提供.
RedirectFromLoginPage 方法生成生成身份驗(yàn)證票后,會調(diào)用FormsAuthentication.Encrypt 方法,將身份驗(yàn)證票加密為字符串,這個(gè)字符串將會是以.ASPXAUTH為名字的一個(gè)Cookie的值。這個(gè)Cookie的其它屬性的生 成:Domain,Path屬性為確省值,Expires視createPersistentCookie參數(shù)而定,若是持久 cookie,Expires設(shè)為50年以后過期;若是非持久cookie,Expires屬性不設(shè)置。
生成身份驗(yàn)證Cookie后,將此Cookie加入到Response.Cookies中,等待發(fā)送到客戶端。
最后RedirectFromLoginPage方法調(diào)用FormsAuthentication.GetRedirectUrl 方法獲取到用戶原先請求的頁面,重定向到這個(gè)頁面。
3. <forms>標(biāo)簽中的timeout和path,是提供了身份驗(yàn)證票寫入到Cookie過期時(shí)間和默認(rèn)路徑。
以上就是基于Forms身份驗(yàn)證的過程,它完成了對用戶身份的確認(rèn)。下面介紹基于Forms身份驗(yàn)證的訪問授權(quán)。
二 訪問授權(quán)
驗(yàn)證了身份,是要使用這個(gè)身份,根據(jù)不同的身份我們可以進(jìn)行不同的操作,處理,最常見的就是對不同的身份進(jìn)行不同的授權(quán),F(xiàn)orms驗(yàn)證就提供這樣 的功能。Forms授權(quán)是基于目錄的,可以針對某個(gè)目錄來設(shè)置訪問權(quán)限,比如,這些用戶可以訪問這個(gè)目錄,那些用戶不能訪問這個(gè)目錄。
同樣,授權(quán)設(shè)置是在你要控制的那個(gè)目錄下的web.config文件中來設(shè)置:
- <authorization>
- <allow users="comma-separated list of users"
- roles="comma-separated list of roles"
- verbs="comma-separated list of verbs" />
- <deny users="comma-separated list of users"
- roles="comma-separated list of roles"
- verbs="comma-separated list of verbs" />
- </authorization>
<allow>標(biāo)簽表示允許訪問,其中的屬性
1. users:一個(gè)逗號分隔的用戶名列表,這些用戶名已被授予對資源的訪問權(quán)限。問號 (?) 允許匿名用戶;星號 (*) 允許所有用戶。
2. roles:一個(gè)逗號分隔的角色列表,這些角色已被授予對資源的訪問權(quán)限。
3. verbs:一個(gè)逗號分隔的 HTTP 傳輸方法列表,這些 HTTP 傳輸方法已被授予對資源的訪問權(quán)限。注冊到 ASP.NET 的謂詞為 GET、HEAD、POST 和 DEBUG。
<deny>標(biāo)簽表示不允許訪問。其中的屬性同上面的。
在運(yùn)行時(shí),授權(quán)模塊迭代通過 <allow> 和 <deny> 標(biāo)記,直到它找到適合特定用戶的第一個(gè)訪問規(guī)則。然后,它根據(jù)找到的第一項(xiàng)訪問規(guī)則是 <allow> 還是 <deny> 規(guī)則來允許或拒絕對 URL 資源的訪問。Machine.config 文件中的默認(rèn)身份驗(yàn)證規(guī)則是 <allow users="*"/>,因此除非另行配置,否則在默認(rèn)情況下會允許訪問。
那么這些user 和roles又是如何得到的呢?下面看一下授權(quán)的詳細(xì)過程:
1. 一旦一個(gè)用戶訪問這個(gè)網(wǎng)站,就行登錄確認(rèn)了身份,身份驗(yàn)證票的cookie也寫到了客戶端。之后,這個(gè)用戶再次申請這個(gè)web的頁面,身份驗(yàn)證票的 cookie就會發(fā)送到服務(wù)端。在服務(wù)端,asp.net為每一個(gè)http請求都分配一個(gè)HttpApplication對象來處理這個(gè)請求,在 HttpApplication.AuthenticateRequest事件后,安全模塊已建立用戶標(biāo)識,就是此用戶的身份在web端已經(jīng)建立起來,這 個(gè)身份完全是由客戶端發(fā)送回來的身份驗(yàn)證票的cookie建立的。
2. 用戶身份在HttpContext.User 屬性中,在頁面中可以通過Page.Context 來獲取同這個(gè)頁面相關(guān)的HttpContext對象。對于Forms驗(yàn)證,HttpContext.User屬性是一個(gè)GenericPrincipal 類型的對象,GenericPrincipal只有一個(gè)公開的屬性Identity,有個(gè)私有的m_role屬性,是string[]類型,存放此用戶是 屬于哪些role的數(shù)組,還有一個(gè)公開的方法IsInRole(string role),來判斷此用戶是否屬于某個(gè)角色。
由于身份驗(yàn)證票的cookie中根本沒有提供role這個(gè)屬性,就是說Forms身份驗(yàn)證票沒有提供此用戶的role信息,所以,對于Forms驗(yàn)證,在服務(wù)端得到的GenericPrincipal 用戶對象的m_role屬性永遠(yuǎn)是空的。
3. GenericPrincipal. Identity 屬性是一個(gè)FormsIdentity類型的對象,這個(gè)對象有個(gè)Name屬性,就是此用戶的標(biāo)示,訪問授權(quán)就是將此屬性做為user來進(jìn)行授權(quán)驗(yàn)證的。 FormsIdentity還有一個(gè)屬性,就是Ticket屬性,此屬性是身份驗(yàn)證票FormsAuthenticationTicket類型,就是之前 服務(wù)器寫到客戶端的身份驗(yàn)證票。
服務(wù)器在獲取到身份驗(yàn)證票FormsAuthenticationTicket對象后,查看這個(gè)身份驗(yàn)證票是不是非持久的身份驗(yàn)證,是的話要根據(jù) web.config中timeout屬性設(shè)置的有效期來更新這個(gè)身份驗(yàn)證票的cookie。
【編輯推薦】