2013-07-09 42 views
0

我使用ASP.NET MVC4構建了一個簡單的Intranet應用程序,該應用程序允許網絡內的用戶查看一些資源。應用程序主要在ExtJS和WebAPI控制器中構建。
我的授權基於Ac​​tive Directory。針對特定用戶的WebAPI存儲變量

調試我的代碼我注意到我正在做多次AD調用。 這裏是我的AD輔助類:

public class AD 
{ 
    public static string CurrentUser = ""; 

    public static string GetCurrentUserLogin() 
    { 
     return HttpContext.Current.User.Identity.Name.Split('\\')[1]; 
    } 

    public static Employee GetCurrentUser() 
    { 
     var login = CurrentUser == "" ? GetCurrentUserLogin() : CurrentUser ; 
     return GetUser(login); 
    } 

    public static Employee GetCurrentUser(string login) 
    { 
     return GetUser(login); 
    } 

    public static Employee GetUser(Guid guid) 
    { 
     using (var entry = new DirectoryEntry("LDAP://wawa.firma.pl/OU=IT,DC=wawa,DC=firma,DC=pl", @"AD_client", "xyzabc")) 
     { 
      using (var searcher = new DirectorySearcher(entry)) 
      { 
       byte[] bytes = guid.ToByteArray(); 

       var sb = new StringBuilder(); 
       foreach (byte b in bytes) 
       { 
        sb.Append(string.Format(@"\{0}", b.ToString("X2"))); 
       } 
       searcher.Filter = String.Format("(&(objectClass=User)(objectCategory=Person)(objectguid={0}))", sb); 
       searcher.PropertiesToLoad.Add("description"); 
       searcher.PropertiesToLoad.Add("objectguid"); 
       searcher.PropertiesToLoad.Add("SN"); 
       searcher.PropertiesToLoad.Add("givenName"); 
       searcher.PropertiesToLoad.Add("name"); 
       searcher.PropertiesToLoad.Add("manager"); 
       searcher.PropertiesToLoad.Add("mail"); 
       searcher.PropertiesToLoad.Add("sAMAccountName"); 
       searcher.PropertiesToLoad.Add("telephoneNumber"); 
       searcher.PropertiesToLoad.Add("directReports"); 
       searcher.SizeLimit = 1; 
       searcher.SearchScope = SearchScope.Subtree; 
       try 
       { 
        SearchResult result = searcher.FindOne(); 
        if (result == null) return null; 

        var emp = ParseSearchResult(result); 
        emp.fullAccess = true; 
        return emp; 
       } 
       catch (Exception) 
       { 
        return null; 
       } 
      } 
     } 
    } 
} 

這工作得很好,但每次我必須讓當前的用戶ID,我也呼籲這樣的:

var user_id = AD.GetCurrentUser().Id; 

我的問題是,每次我要求存儲在AD中的用戶的一些屬性,我必須做新的AD呼叫。 理想情況下,我想做一次簡單的調用(對於當前用戶)並存儲它,然後每當我需要某些東西時,我都會從本地對象中獲取它。

我讀到會議的WebAPI控制器,例如一些文章:http://stick2basic.wordpress.com/2013/04/18/how-to-access-session-in-web-api-controller-in-mvc4/,但我也發現,使用緩存的馬麗娟例如:https://github.com/filipw/AspNetWebApi-OutputCache

但會話是按用戶和應用程序緩存。

什麼是每個用戶存儲ActiveDirectory結果的最佳方式?我應該如何修改我的AD類來保存這些變量。

最簡單的方法是將存儲導致會話像這樣:

public static Employee GetUser(Guid guid) 
{ 
    var e = HttpContext.Current.Session[guid.ToString()] as Employee; 
    if (e == null) 
    { 
     //get user from AD 
     //store in session 
    } 
    return e; 
} 

這樣我就可以查詢AD只有一次,但我不能夠每n分鐘重新查詢(緩存有超時)。

我該如何讓這更容易/更好?還有其他方法可以做到這一點嗎?

+0

您可以使用'Dictionary '來永遠緩存它,應該是足夠的數據結構。或者你可以使用'System.Runtime.Caching'來緩存TTL值。 – Seph

+0

@Seph - 我想保持30分鐘,因爲有時AD對象可以改變(例如特權),我想在一段時間後加載這些更新。會話是每個用戶,但與詞典<字符串,員工>我可以存儲每個員工緩存,因爲他們將有獨特的指導。因此,擁有該字典的緩存對象可以只刷新特定的員工嗎?我可以爲整個Cached對象設置過期期限,但是我可以爲該Dictionary元素執行相同的操作嗎? – Misiu

+0

,因爲@oeoren會使用'System.Runtime.Caching'進一步解釋。 – Seph

回答

0

您需要一些內存緩存。看看:MemoryCache Class

將DirectoryEntry對象存儲在緩存中,路徑爲鍵。