2015-05-29 12 views
4

我們有一個非常大的網頁應用程序,有很多頁面。這些頁面要求我們瞭解用戶的角色以正確顯示內容。所以在Application_AuthenticationRequest,我們有這樣的代碼:如何持久化Application_AuthenticateRequest中所需的會話特定值?

var id = new GenericIdentity(Request.Headers["ceid"]); 
var rp = new MyRoleProvider(); 
var principal = new GenericPrincipal(id, rp.GetRolesForUser(id.Name)); 
Context.User = principal; 

的問題是,我們需要使用Web服務來獲取角色,並因爲呼叫正在盡一切每次用戶訪問一個頁面時,網頁服務正遭受太多次打擊。

理想的解決辦法是,如果我們可以在角色存儲在一個會話變量,不過,會議沒有Application_AuthenticateRequest可用。我們考慮在應用程序變量中存儲一個包含所有用戶條目的字典,但我希望能找到更好的解決方案。

有沒有我們可以存儲在這樣一種方式,他們將可裏面Application_AuthenticationRequest當前用戶的角色什麼辦法?我們非常安全,一個cookie是否是一個有效的選擇?

+2

您是否知道有外的即用功能,以「緩存」用戶的角色在cookie ? https://msdn.microsoft.com/en-us/library/system.web.security.roles.cacherolesincookie%28v=vs.110%29.aspx –

+0

如果你想使用Roles API,很多人都是自己的角色,因此存儲在具有HttpOnly(僅在服務器上可用)設置爲true的cookie是一個很好的解決方案。 –

+0

如果您不喜歡使用cookie,可能是[MemoryCache](https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache%28v=vs.110%29.aspx)是可能的解決方案? –

回答

1

我想創建一個靜態類來保存我們的當前所有用戶(基本上擴展你的字典的想法)的角色列表:如果給定ID的角色都沒有出現在列表中,我們從Web服務進行檢索。否則,我們返回存儲的角色。

我們需要的手段一定量的用戶不活動後過期數據(我們不希望繼續對所有用戶的所有角色在內存中的所有次),所以我們將實現我們自己的到期機制(20分鐘,我的例)。

這是我會怎麼寫的課,我會怎麼使用它:

/// <summary> 
    /// This is the static class that will hold the roles for all active users (active users 
    /// are those that have been using the website within the last 20 minutes). 
    /// </summary> 
    public static class MyRoles 
    { 
     /// <summary> 
     /// This class holds your roles 
     /// </summary> 
     private class Principal 
     { 
      private DateTime lastAccess; // Our expiration timer 
      private System.Security.Principal.GenericPrincipal principal; // Our roles 

      public Principal(System.Security.Principal.GenericPrincipal principal) 
      { 
       this.principal = principal; 
       this.lastAccess = DateTime.Now; 
      } 

      public System.Security.Principal.GenericPrincipal GenericPrincipal 
      { 
       get 
       { 
        // We reset our timer. It will expire 20 minutes from now. 
        this.lastAccess = DateTime.Now; 

        return principal; 
       } 
      }         

      /// <summary> 
      /// This tells us if a user has been active in the last 20 minutes 
      /// </summary> 
      public bool IsValid 
      { 
       get 
       { 
        // Valid within 20 minutes from last call 
        return DateTime.Now <= this.lastAccess.AddMinutes(20);       
       } 
      } 
     } 

     /// <summary> 
     /// This will hold IDs and related roles 
     /// </summary> 
     private static Dictionary<string, Principal> ids = new Dictionary<string, Principal>(); 

     /// <summary> 
     /// Method to retrieve roles for a given ID 
     /// </summary> 
     /// <param name="header">Our ID</param> 
     /// <returns></returns> 
     public static System.Security.Principal.GenericPrincipal GetRoles(string header) 
     { 
      if (ids.ContainsKey(header) && ids[header].IsValid) 
      { 
       // We have roles for this ID 
       return ids[header].GenericPrincipal; 
      } 
      else 
      { 
       // We don't have this ID (or it's expired) so get it from the web service 
       var id = new System.Security.Principal.GenericIdentity(header); 
       var principal = new System.Security.Principal.GenericPrincipal(id, new MyRoleProvider().GetRolesForUser(id.Name)); 

       // Store roles 
       ids.Add(header, new Principal(principal)); 

       return principal; 
      } 
     }    
    } 

    protected void Application_AuthenticateRequest(object sender, EventArgs e) 
    { 
     // This is how we use our class 
     var principal = MyRoles.GetRoles(Request.Headers["ceid"]); 
    } 

請注意,我的示例代碼不考慮存儲的GenericPrincipal實例列表所需的內存佔用。我的目標僅僅是讓您瞭解如何在不使用會話對象的情況下堅持(和終止)用戶數據。

20分鐘到期機制可以很容易地鏈接到Session_End事件,因此只要會話結束(如果您使用InProc會話),它就會過期數據。

也請注意,就像會話,此解決方案僅適用於單服務器環境。如果您有一個負載平衡的環境(2臺或更多臺Web服務器),則必須將數據保存到數據庫。

我希望這可以幫助你。如果沒有,請讓我知道爲什麼,我會盡我所能來幫助你:)

+0

謝謝,@Alex ...我會盡快嘗試。對不起,但我的VS2013的試用版剛剛過期,我爲一家大公司工作,所以讓他們給我一個實際的MSDN許可證需要的時間比預期的要長:( –

+0

沒問題,@FrancineDeGroodTaylor。只要記住保持關注那個靜態類的內存佔用情況(就像你使用Session對象時一樣)如果你需要我,你知道在哪裏找到我:) –