[轉]Asp.Net 使用者驗證(自訂IPrincipal和IIdentity)

來源:互聯網
上載者:User

標籤:current   post   cti   arc   .com   gis   thread   ace   event   

本文轉自:http://www.cnblogs.com/amylis_chen/archive/2012/08/02/2620129.html

Default.aspx 頁面預覽預設情況下SignIn.aspx在登入成功後會導航到Default.aspx頁面,所以我們先簡單的構建一下Default.aspx頁面,看看實現的效果:<asp:LoginView ID="LoginView1" runat="server">    <AnonymousTemplate>        歡迎訪問, 遊客 !          </AnonymousTemplate>    <LoggedInTemplate>        你好, <asp:LoginName ID="LoginName1" runat="server" /> ! <br />        <strong>UserData值:</strong>        <asp:Literal ID="lbUserData" runat="server" />    </LoggedInTemplate></asp:LoginView><br /><asp:LoginStatus ID="LoginStatus1" runat="server" LogoutPageUrl="~/Logout.aspx" LogoutAction="Redirect" />類似地,我們放置了一個LoginView控制項,只是這裡我們多放置了一個LoginStatus控制項。接下來我們看一下後置代碼:protected void Page_Load(object sender, EventArgs e) {    if (!IsPostBack) {        if (Request.IsAuthenticated) {            FormsIdentity identity = User.Identity as FormsIdentity;            string userData = identity.Ticket.UserData;            Literal lbUserData = LoginView1.FindControl("lbUserData") as Literal;            lbUserData.Text = userData;        }    }}最後我們先進行登入,然後再開啟Default.aspx頁面,會看到類似這樣的輸出:至此,我們已經看到了如何利用FormsAuthentionTicket來附帶額外的使用者資料,但是我們應該看到這種做法存在的問題:可以儲存的資料過於單一,僅僅只是一個字串。而我們第一節中所介紹的使用者表包括各種類型的各種資料。如果你看過了 從一個範例看XML的應用 這篇文章,你應該立刻想到此處又是一個“單一字串儲存多種不同類型資料”的應用情境,我們可以定義XML來解決。對於這種方式,我不再示範了。實際上,我們可以自訂一個IPrincipal和IIdentity來完成,接下來就來看一下。自訂IPrincipal和IIdentity不管是在Windows上還是在Web上,.Net都使用這兩個介面來實現使用者的身分識別驗證。它們不過是一個介面,實現了這兩個介面的類型附帶了使用者的資訊,最終被賦予線程(Windows)或Cookie(Web)來對使用者進行驗證。我們在App_Code下添加CustomPrincipal和CustomIdentity來實現這兩個介面:public class CustomPrincipal : IPrincipal {    private CustomIdentity identity;    public CustomPrincipal(CustomIdentity identity) {        this.identity = identity;    }    public IIdentity Identity {        get {            return identity;        }    }    public bool IsInRole(string role) {        return false;    }}public class CustomIdentity : IIdentity {    private FormsAuthenticationTicket ticket;    private HttpContext context = HttpContext.Current;    public CustomIdentity(FormsAuthenticationTicket ticket) {        this.ticket = ticket;    }    public string AuthenticationType {        get { return "Custom"; }    }    public bool IsAuthenticated {        get { return true; }    }    public string Name {        get {            return ticket.Name;        }    }    public FormsAuthenticationTicket Ticket {        get { return ticket; }    }    // 這裡可以是任意來自資料庫的值,由Name屬性取得    // 需要注意此時已通過身分識別驗證    public string Email {        get {            HttpCookie cookie = context.Request.Cookies["Email"];            if (cookie==null || String.IsNullOrEmpty(cookie.Value)) {                string type = "jimmy_dev[at]163.com";   // 實際應根據name屬性從資料庫中獲得                cookie = new HttpCookie("UserType", type);                cookie.Expires = DateTime.Now.AddDays(1);                context.Response.Cookies.Add(cookie);            }            return cookie.Value;        }    }    public string HomePage {        get {            HttpCookie cookie = context.Request.Cookies["HomePage"];            if (cookie==null || String.IsNullOrEmpty(cookie.Value)) {                string name = "www.tracefact.net";      // 實際應根據name屬性從資料庫中獲得                cookie = new HttpCookie("NickName", name);                cookie.Expires = DateTime.Now.AddDays(1);                context.Response.Cookies.Add(cookie);            }            return cookie.Value;        }    }}注意這裡的HomePage和Email這兩個屬性,它們攜帶了我們的使用者資料,這裡我僅僅是對它們進行了一個簡單的賦值,實際的數值應該是來自於資料庫。還要注意擷取到它們的值後被儲存在了Cookie中,以避免頻繁的對資料庫進行訪問。定義了實現這兩個介面的對象之後,我們還需要把它嵌入到應用程式的生命週期中,具體的做法就是掛接到HttpModule或者是重寫Global.asax中的事件,這裡我採用了重寫Global.asax事件的方式,因此建立一個Global.asax檔案,然後添加如下代碼:void Application_OnPostAuthenticateRequest(object sender, EventArgs e) {    IPrincipal user = HttpContext.Current.User;    if (user.Identity.IsAuthenticated        && user.Identity.AuthenticationType == "Forms") {        FormsIdentity formIdentity = user.Identity as FormsIdentity;        CustomIdentity identity = new CustomIdentity(formIdentity.Ticket);        CustomPrincipal principal = new CustomPrincipal(identity);        HttpContext.Current.User = principal;        Thread.CurrentPrincipal = principal;    }}這段代碼很好理解,它不過是在應用程式的PostAuthenticateRequest事件中用我們自訂的CustomPrincipal和CustomIdentity替換掉了預設的IPrincipal和IIdentity實現。Default.aspx頁面預覽我們再次對Default.aspx進行修改,添加兩個Literal控制項,用於顯示我們自訂的數值:自訂Identity中的值:<br /><strong>Email:</strong><asp:Literal ID="ltrEmail2" runat="server"></asp:Literal><br /><strong>HomePage:</strong><asp:Literal ID="ltrHomePage" runat="server"></asp:Literal><br />然後修改頁面的代碼,使用我們的自訂CustomIdentity,然後從中獲得自訂的屬性值:protected void Page_Load(object sender, EventArgs e) {    if (!IsPostBack) {        if (Request.IsAuthenticated) {            CustomIdentity identity = User.Identity as CustomIdentity;            if (identity != null) {                // 獲得UserData中的值                string userData = identity.Ticket.UserData;                Literal lbUserData = LoginView1.FindControl("lbUserData") as Literal;                lbUserData.Text = userData;                // 獲得identity中的值                ltrEmail2.Text = identity.Email;                ltrHomePage.Text = identity.HomePage;            }        }    }}如果你現在開啟頁面,將會看到類似下面的頁面:可以看到我們獲得了定義在CustomIdentity中的屬性。注意這裡我只是做了一個示範,因此只在CustomIdentity中包含了Email和HomePage兩個屬性值,如果看到此處你便以為大功告成,然後將所有未完成的屬性都添加到CustomIdentity中去就大錯特錯了。Identity的目的只是為你提供一個已經登入了的使用者的名稱,而不是攜帶所有的使用者資訊,這些資訊應該由其他的類型提供。因此微軟才定義了MemberShipUser類型和Profile。從這個角度上來看,自訂IPrincipal和IIdentity並沒有太大的意義。這裡,我們最好是定義一個自己的類型來承載使用者資料,下面我們就看下如何完成。自訂類型攜帶使用者資料在App_Code中建立一個SiteUser類,它的實現如下,簡單起見,我使用了公有欄位而非屬性:public class SiteUser{    public string Name;    public string UserImage;    public DateTime RegisterDate;    public string Email;    public string HomePage;    public int PostCount;    public int ReplyCount;    public byte Level;    public SiteUser(AuthDataSet.UserRow userRow) {        this.Email = userRow.Email;        this.HomePage = userRow.Homepage;        this.Level = userRow.Level;        this.Name = userRow.Name;        this.PostCount = userRow.PostCount;        this.RegisterDate = userRow.RegisterDate;        this.ReplyCount = userRow.ReplyCount;        this.UserImage = userRow.UserImage;    }    // 實際應該由資料庫獲得    public static SiteUser GetUser(string name) {        AuthDataSetTableAdapters.UserTableAdapter adapter            = new AuthDataSetTableAdapters.UserTableAdapter();        AuthDataSet.UserDataTable userTable = adapter.GetUserTable(name);                if(userTable.Rows.Count >0){            return new SiteUser((AuthDataSet.UserRow)userTable.Rows[0]);        }        // 因為調用這個方法時,name應該是有效,        // 如果name無效,直接拋出異常        throw new ApplicationException("User Not Found");    }}它的GetUser()靜態方法根據使用者的名稱獲得了一個SiteUser對象,這裡需要注意的是通常調用這個方法時,使用者已經登入過了,也就是說其name參數總是有效,因此當搜尋資料庫找不到記錄時,我簡單地拋出了異常。

 

[轉]Asp.Net 使用者驗證(自訂IPrincipal和IIdentity)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.