ASP.NET专题研究——角色和Profile
(一)用戶角色的問題:
??????????? 匿名用戶和非匿名用戶雖然可以在一定程度上避免訪問人數太多帶來的管理紊亂和安全性問題,但是僅有這項是遠遠不夠的。為了職責明確,避免不必要的糾葛和扯皮的事情發生,在后臺網站管理上通常我們會給不同登錄的人員分配不同的任務,賦予它們訪問不同頁面的權限。我們通常把這種稱之為“用戶角色”(Role)。
??????????? 在ASP.NET中啟用用戶角色非常簡單——只需解決方案管理器右上角的一個(榔頭+地球)的圖標,進入頁面之后點擊“Enabled Role”,然后添加一些角色名稱(隨便,比如admin,guest,user等)。啟用Role在web.config對應的代碼也是異常簡單:
<roleManager enabled="true" cacheRolesInCookie="true">
</roleManager>
??????????? 如果你要對某個頁面(或者某個路徑下所有頁面)權限限制,只要這樣做:
<location path="Default2.aspx">
??? <system.web>
????? <authorization>
??????? <allow roles=”admin”/>
??????? <deny roles=”*” />
????? </authorization>
??? </system.web>
?</location>
這樣一來,不是admin權限的人就不能訪問這個頁面了(會出錯的,說頁面找不到)。不過這一個頁面太“土”,您完全可以配置自己的頁面,在web.config中這樣配置:
<customErrors mode="RemoteOnly" >
<error statusCode="403" redirect="NoAccess.htm" />
</ customErrors>
?
(二)Profile(個性文件)配置:
??????????? 如果你上百度、Google等一些大型網站,您會發現即便你沒有登錄,你照樣也可以對某些頁面進行設置(比如調整背景色、大小等)。稍后你關閉頁面,隔一段時間之后打開仍然是你原先設置的樣子,這個效果通常被我們成為個性配置(Profile)。
??????????? 以往在傳統WinForm程序中,保留這種個性配置可以通過讀寫xml文件和(反)序列化以達到目的。但是Web程序是無狀態連接,同時其機制也迫使其不可能像WinForm程序一樣可以把所有配置一股腦兒地往客戶端那兒拋,然后由服務器讀取。在最初的一段日子里,我們經常用Session存儲每一個私有用戶的信息,但是Session一旦用戶中斷連接(無論正常與否)結果Session的東西全部被丟棄了。如果放到Cookie里呢,Cookie只能存儲字符串,不能存儲大量對象的東西。所以我們急迫需要一種新技術——該技術既可以以對象的模式記錄每一個用戶的內容,同時還要保證客戶端即便中斷也不丟失信息。這種技術在ASP.NET2.0中已經被實現,成為Profile。
??????????? 比如一個用戶訪問百度的頁面(假設是ASP.NET開發該頁面),那么我們要記住他曾經第一次設置的背景色,以便下次訪問仍舊記住該背景色(個性化)。我們可以按照以下步驟在前幾章的基礎上進行配置:
1、配置Profile(web.config):
<anonymousIdentification enabled="true"/>
<profile automaticSaveEnabled="true">
????? <properties>
?????? ???? ?<add allowAnonymous="true" defaultValue="White" />
????? </properties>
</profile>
這里注意幾點:
?????????????? “anonymousIdentification”:表示啟用匿名機制。
?????????????? “automaticSaveEnabled”:表示當使用Profile的地方頁面(被)提交的時候,自動寫入數據庫對應的profile中所有東西(如果是false,您必須使用Profile.Save()強行寫入數據庫)。
?????????????? “allowAnonymous”:表示當前的這個可被記錄的屬性是否支持匿名。
?
2、現在我們再次回到前面那個“個性化設置背景色”問題——假設你的頁面是這樣設計的(加粗體字是因為原來生成的頁面代碼中不包含此類相關信息,為了便于后臺控制):
<body id="mybody" runat="server">
……
??????????? 先請您在Page_Load中代碼這樣寫:
protected void Page_Load(object sender, EventArgs e)
??? {
??????? mybody.Style[HtmlTextWriterStyle.BackgroundColor] = Profile.BackColor;???? //動態設置BackColor的內容,注意到Profile.的時候,智能感知出來BackColor的提示了嗎?可見Profile是強類型的。
??? }
隨后放上一個按鈕,然后在按鈕中簡單寫這樣的代碼:
protected void Button1_Click(object sender, EventArgs e)
{
??????????? Profile.BackColor = “Blue”;
}
點擊按鈕,然后關閉瀏覽器,然后打開頁面,是不是背景色發生變化了?很有意思吧?
(三)Profile多類型嵌套:
??????????? 有時為了比較系統化、正規化描述一個人的特征(比如身高、年齡。性別等)。我們往往可以這樣做:
<profile automaticSaveEnabled="true">
????? <properties>
??????? ??? <group>
???????? ?????????????? ?<add/>
????????? ????????????? <add/>
????????? ????????????? <add/>
?????? ???? ?</group>
????? </properties>
??? </profile>
然后我可以這樣調用代碼:Profile.Person.Sex/Age/name….
Group標簽就是用于嵌套屬性的,原則上可以嵌套N個屬性,而且可以為每個屬性指定是否匿名等特性。同時,大家應該注意到一個問題,Age和Sex的類型不應該是String的(因為默認是String)類型,所以我在此地強制指定了它們的類型。現在帶來一個新問題——如果某個Profile的屬性是自定義類型呢?
(四)Profile的自定義類型:
??????????? 在Profile中,自定義變得非常直觀而且簡單:
<profile automaticSaveEnabled="true">
????? <properties>
????????? ? <add type='InfoList' serializeAs='Binary'/>
????? </properties>
</profile>
注意:type這里的完整寫法是“命名空間.類名”,但是由于InfoList沒有命名空間(直接在App_Code文件夾下),所以允許這樣寫;同時必須把這個類表示成[Serializable],以便序列化后寫入數據庫(Binary的形式)。
(五)匿名用戶和登錄用戶的Profile:
??????????? 現在無論是淘寶、網易,還是百度的商品拍賣網站上都有“購物車”,其大致可以允許你暫時在未登錄的情況下先選擇物品添加進入購物車,然后結賬的時候登錄,成功以后把所有匿名選擇的物品轉移到已登陸的那個帳號。這功能很容易實現嗎?我們先看一個小例子(方便起見,這里只在Person下弄一個Cart的字符串數組):
protected void Page_Load(object sender, EventArgs e)
??? {
??????? if (!IsPostBack)
??????? {
??????????? ProfileManager.DeleteInactiveProfiles(ProfileAuthenticationOption.All, DateTime.Now);
??????????? Profile.Person.Cart = "蘋果";
??????????? Profile.Save();
??????????? Response.Write("用戶名?:" + Profile.UserName);
??????????? Response.Write("購物情況?:" + Profile.Person.Cart);
??????? }
??????
??? }
protected void Button1_Click(object sender, EventArgs e)
??? {
??????? FormsAuthentication.SetAuthCookie("abd", true);
??????? Response.Write("用戶名:" + Profile.UserName);
??????? Response.Write("購物情況:" + Profile.Person.Cart);
??? }
或許我們以為:點擊Click提交以后自然會把abc賦值給UserName屬性,并且一同把數值帶來了,但是實際并非我們想象那么簡單:結果你會發現“用戶名”雖然是abc,但是Cart卻空了(丟失數據了?)
這里的原因非常簡單:因為Profile在匿名存儲數據的時候,會發送一個隨機的Cookie給客戶端(Id是唯一的),然后寫入數值。但是你登錄以后,原先的憑證就被作廢,自動換一個新的憑證了。所以解決方案就是在SetAuthCookie的時候必須獲取原來那個即將丟失的憑據,然后賦值給當前的Profile。
這里提供一個解決方案(在Global.asax加入以下代碼):
? void Profile_MigrateAnonymous(Object s,
?? ???ProfileMigrateEventArgs e)
??? {
??????? ProfileCommon anonProfile = Profile.GetProfile(e.AnonymousID);????????? //通過該方法將獲得匿名用戶的Profile
??????? Profile.Person.Cart = anonProfile.Person.Cart;?? //重新賦值給當前的Profile
??? }??
(六)Profile的清理工作
??????????? 你的網站曾經被大量的“匿名”和“登錄”用戶訪問,結果造成你的aspnet_profile數據庫中擠滿了一堆不需要的垃圾數據。您可以清理。清理的方法當然也是直接使用ProfileManager.DeleteInactiveProfiles,其具體參數如下:
ProfileManager.DeleteInactiveProfiles(ProfileAuthenticationOption.All, DateTime.Now.AddDays(-7));
其中“ProfileAuthenticationOption”是一個枚舉,指示刪除的Profile的范圍(全部All,登錄用戶Authenticated和匿名用戶Anoymous)。而DateTime是刪除在此日期前(包括此日期自身)的Profile,如上面的代碼所示:刪除距離現在7天前的所有用戶的Profile。
轉載于:https://www.cnblogs.com/serviceboy/archive/2010/04/23/1718417.html
總結
以上是生活随笔為你收集整理的ASP.NET专题研究——角色和Profile的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步一步学Silverlight 2系列
- 下一篇: Spring.NET实用技巧3——NHi