2012年5月31日 星期四

ASP.Net 使用 Form 認證設定使用者登入資訊

在 ASP.Net 專案,如果使用的認証方式為 Form 認證,當確認了登入者身份後, 會將使用者是否已經經過認證的訊息寫到 Cookie裡,而 Cookie 名稱為 ASPXAUTH。透過以下方法,可以看到 Cookie 的值。

Request.Cookies[“ASPXAUTH”].Value

或是用下面這段迴圈去抓出目前的 Cookie 資訊:
StringBuilder sb = new StringBuilder();
        
for (int i = 0; i < Request.Cookies.Count; i++)
{
     sb.Append(string.Format("<br>Name:{0} Values:{1}", Request.Cookies[i].Name,Request.Cookies[i].Value));
}

lb_Cokies_info.Text=sb.ToString();

當然,你所看到的 Cookie 值是經過編碼加密後的一串文字。
剛剛提到,確認並通過了使用者身份後,會將資訊寫到 Cookie 裡,那這寫入的動作,是誰做?不用想太多,當然是程式設計師自己去做啦~

介紹目前自己常常看到的三種寫入認證 Cookie 方式:

一、RedirectFromLoginPage()
舉例來說,假設使用者 paladin 填寫完帳號密碼,並檢查無誤後,就可以用下面語法將 “paladin” 這帳號訊息寫到 ASPXAUTH Cookie裡。所以RedirectFromLoginPage 方法裡的第一個參數,是用來存放被認可的使用者帳號資訊。

第二個參數還蠻值得玩味的,官方說法是表示建立持久性 Cookie (跨瀏覽器工作階段儲存的 Cookie) (Ref.http://msdn.microsoft.com/zh-tw/library/bk50ykcd.aspx) )。經實際測試後,所謂的跨瀏覽器並不是跨 IE、Chrome、Firefox,而是指是否允許在另開 IE 瀏覽器時使用同一份 Cookie,所以IE 裡的 ASPXAUTH Cookie 與 Chrome 或 Firefox 都不一樣,他們都有各自的 Cookie。但如果你是使用開啟新索引標籤的方式,則不管值為何,都是使用同一份 Cookie,每一個標籤都抓的到。

此外,當第二個參數設為 true 時,預設 Cookie 的存活時間約 30 分鐘,也就是說,當你把所有瀏覽器都關閉時,在30分鐘內都還可以存取到有效的 Cookie 值。但如果參數設為 false,則當視窗都關閉後,Cookie也就會自動失效。
using System.Web.Security;

FormsAuthentication.RedirectFromLoginPage(“paladin”, false);

此外,使用RedirectFromLoginPage()方法時,顧名思義當他執行完後,應該會把頁面轉到(Redirect)其他頁面去吧,實際上也真是如此。當執行完後,他會先檢查目前的 URL 裡是否有設定 ReturnUrl,如果有,就會將頁面轉到  ReturnUrl 所定義的頁面。舉例來說,如果你的驗證登入的頁面是:



http://paladin.love.girl.tw/login.aspx?ReturnURL=hello_baby.aspx

當執行 RedirectFromLoginPage() 方法後,你的頁面就會轉到

http://paladin.love.girl.tw/hello_baby.aspx



但如果你忘了或不想在 URL 上面指定 ReturnURL 參數,那也沒關係,他會根據目前 FormsAuthentication.DefaultUrl 所定義的值來決定歸處,但預設值是 default.aspx。這裡需要注意的是,FormsAuthentication.DefaultUrl 只能取得他的值,卻不可直接設定他,如果真要改變的話,需在 web.config 裡的 defaultUrl 調整(Ref.FormsAuthentication.DefaultUrl 屬性)。


<authentication mode="Forms">
  <forms loginUrl="member_login.aspx"
    defaultUrl="index.aspx" />
</authentication>

二、SetAuthCookie()
如果對於 ReturnURL 還耿耿於懷,或是希望自己能夠完全主導認證後頁面轉向的控制權,則可以使用 SetAuthCookie() 方法來完成。他的使用方式跟前面的 RedirectFromLoginPage() 非常相似,舉例來說:


FormsAuthentication.SetAuthCookie(“paladin”, false);

第一個參數是將登入者的帳號寫到 ASPXAUTH Cookie 裡,第二個參數也跟RedirectFromLoginPage() 一樣,用來表示是否建立持久性 Cookie。最大的不同,在於SetAuthCookie() 執行完後,不會將你目前的頁面帶離,而是留給程式設計師自行決定。

三、FormsAuthenticationTicket
前面兩種作法,都算是輕巧簡便型,他們把很多複雜的設定都封裝起來,所以用起來很方便,但從另一個角度來說,也就失去許多原本可以設定的選項,變得比較沒有彈性。如果希望自己撰寫個比較有彈性的寫法,可以利用 FormsAuthenticationTicket 類別來實作。以一段程式來說明:

      bool isPersistent = false;

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
            1,
            "paladin",
            DateTime.Now,
            DateTime.Now.AddMinutes(30),
            isPersistent,
            "Admin",
            FormsAuthentication.FormsCookiePath
            );

        // Encrypt the ticket.
        string encTicket = FormsAuthentication.Encrypt(ticket);


        HttpCookie authenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);

        //將HttpCookie是否永久存在的屬性與FormsAuthenticationTicket綁在一起
        if (isPersistent)
            authenticationCookie.Expires = ticket.Expiration;

        // Create the cookie.
        Response.Cookies.Add(authenticationCookie);


首先建立了一個 FormsAuthenticationTicket 類別,建構式裡有7個參數可以設定。
1.設定 ticket 的版本
2.設定要存放的使用者帳號
3.設定 ticket 產生的時間
4.設定 ticket 過期時間
5.設定這個 ticket 是否是持續的
6.允許使用者任意輸入的文字(但不是無限制長度,Cookie 能保存的文字長度有限制)
7.Cookie 存放路徑

這裡的參數設定,主要針對第六個參數要特別注意。通常我們確認了使用者身份,且將使用者的帳號記錄下來後,還有可能會進一步去將他的群組資料也放進去。例如使用者是「Admin」還是「Guest」,或是同時具備多種群組身份。第六個參數允許你存放的是字串格式,可以拿來存放群組資訊。如果準備存放多種群組角色時,一般都可以使用 | 或其他分隔字元來區別,例如:Admin|Guest 。但當你在使用時,需特別注意,因為 Cookie 的長度並非無限制,如果將太多的資訊(例如:分機、住址...)都全部往裡面寫,那就有可能會造成錯誤,所以盡可能寫比較重要且精簡的內容,過多的相關資訊,可以考慮存放索引值就好,需要用到時再去資料庫反查。


最後,我們可以透過以下方式取得先前所存放的使用者資訊:





//取得使用者帳號
        if (User.Identity.IsAuthenticated)
        {
            lbUserInfo.Text = string.Format("目前登入者帳號為:{0}", User.Identity.Name);
        }
        else
        {
            lbUserInfo.Text = "目前尚未登入";
        }

//取得使用者自訂資料
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null) return;
FormsAuthenticationTicket authTicket =FormsAuthentication.Decrypt(authCookie.Value);
Response.Write(authTicket.UserData);



以上一切的一切,都是假設您是使用 Form 認證才會成立的,所以在 web.config 中,必須確認有以下的設定喔。
<authentication mode="Forms">

參考:
01.概略解釋 Forms Authentication 的運作

沒有留言:

張貼留言