Asp.net-Mvc-3

如何初始化授權資訊

  • February 27, 2014

好的,所以這似乎是一個常見的需求。用Google搜尋可以找到很多方法來做到這一點。我對最“mvc 正確”的方式感興趣。

在我的應用程序的右上角,我有一個問候語,上面寫著Hello FirstName LastNameIPrincipal現在,通過(aka User.Identity.Name)很容易獲得登錄使用者的使用者名。但是,這不會給我使用者的名字和姓氏。我必須點擊 Membership API 來獲得它。

使用 Membership API 有其缺點。它每次都會訪問數據庫,這會為每個服務頁面添加額外的數據庫訪問權限。在登錄時設置一些會話變數很容易,但這僅適用於該會話。如果使用者點擊“記住我”,則下次不會登錄,我仍然必須載入這些值。

  1. 我可以創建自己的成員資格提供程序來進行一些記憶體,但這對於或多或少的單一目的來說是很多工作。
  2. 我可以使用Application_AuthenticateRequest並點擊會員 api 並將值儲存在會話變數或類似的東西中。這沒關係,但似乎有點蠻力。
  3. 我可以註冊一個全域過濾器並處理 OnAuthenticate,基本上做同樣的事情。這似乎好一點,但我不使用這裡的後果。
  4. 我可以派生一個基本控制器,並簡單地添加屬性來提供此資訊。這似乎有點“老派”,我討厭為了一個單一的目的而必須創建一個基類。
  5. 我可以創建一個記憶體靜態方法來獲取首次訪問的資訊。這基本上不比單例好多少。
  6. 我也可以創建我自己的 IPrincipal,但這意味著每次都要使用它來獲取數據,這似乎很笨拙。我可以將它包裝在另一個類中以簡化它,但仍然……
  7. 我可以將數據儲存在表單身份驗證 cookie 中,然後從那裡獲取。有一些工具可以讓這更容易。

有沒有我沒有想到的方法?什麼是最“mvc正確”的做法?

我認為最好的方法是使用 Cookie。這是我在項目中使用的解決方案:

創建一個類以在其中保存數據

[DataContract]
[Serializable()]
public class AuthData {

   [DataMember]
   public String UserName { get; set; }

   [DataMember]
   public String FirstName { get; set; }

   [DataMember]
   public String LastName { get; set; }

   [DataMember]
   public String Email { get; set; }

   // any other property you need to a light-store for each user

   public override string ToString() {
       string result = "";
       try {
           using (MemoryStream stream = new MemoryStream()) {
               BinaryFormatter formatter = new BinaryFormatter();
               formatter.Serialize(stream, this);
               result = Convert.ToBase64String(stream.ToArray());
           }
       } catch (Exception ex) {
           throw new HttpException(ex.Message);
       }
       return result;
   }

   static public AuthData FromString(String data) {
       AuthData result = null;
       try {
           byte[] array = Convert.FromBase64String(data);
           using (MemoryStream stream = new MemoryStream(array)) {
               stream.Seek(0, 0);
               BinaryFormatter formatter = new BinaryFormatter();
               result = (AuthData)formatter.Deserialize(stream, null);
           }
       } catch (Exception ex) {
           throw new HttpException(ex.Message);
       }
       return result;
   }
}

簽到方式:

public static bool SignIn(string userName, string password, bool persistent){
   if (Membership.ValidateUser(userName, password)) {
       SetAuthCookie(userName, persistent);
       return true;
   }
   return false;
}

設置 AuthCookie:

public static void SetAuthCookie(string userName, bool persistent) {
   AuthData data = GetAuthDataFromDB(); // implement this method to retrieve data from database as an AuthData object
   var ticket = new FormsAuthenticationTicket(
       1, 
       userName, 
       DateTime.Now,
       DateTime.Now.Add(FormsAuthentication.Timeout), 
       persistent, 
       data.ToString(), 
       FormsAuthentication.FormsCookiePath
       );
   string hash = FormsAuthentication.Encrypt(ticket);
   HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
   cookie.Expires = DateTime.Now.Add(FormsAuthentication.Timeout);
   cookie.HttpOnly = false;
   cookie.Path = FormsAuthentication.FormsCookiePath;
   HttpContext.Current.Response.Cookies.Add(cookie);
}

獲取 AuthCookie:

public static AuthData GetAuthCookie() {
   if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.User.Identity is FormsIdentity) {
       FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
       FormsAuthenticationTicket ticket = id.Ticket;
       var data = AuthData.FromString(ticket.UserData);
       HttpContext.Current.Items["AuthDataContext"] = data;
       return data;
   }
   return null;
}

在 ControllerBase 中:

private AuthData _authData;
private bool _authDataIsChecked;
public AuthData AuthData {
   get {
       _authData = System.Web.HttpContext.Current.Items["AuthDataContext"] as AuthData;
       if (!_authDataIsChecked && _authData == null) {
           SignService.GetAuthCookie();
           _authData = System.Web.HttpContext.Current.Items["AuthDataContext"] as AuthData;
           _authDataIsChecked = true;
       }
       return _authData;
   }
}

引用自:https://stackoverflow.com/questions/7279541