2011-09-02 90 views
10

好的,所以這似乎是一種常見的需求。有一點谷歌搜索發現很多方法來做到這一點。我對最「mvc正確」的方式感興趣。如何初始化授權信息

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

碰到會員API有其缺點。它每次都會訪問數據庫,從而爲每個提供服務的頁面添加額外的數據庫訪問權限。在登錄時很容易設置一些會話變量,但這隻適用於該會話。如果用戶點擊「記住我」,那麼下次不會登錄,我仍然需要加載這些值。

  1. 我可以創建自己的成員資格提供程序來執行一些緩存操作,但這對於或多或少的單一目的來說是很多工作。
  2. 我可以使用Application_AuthenticateRequest並擊中成員api並將值存儲在會話變量中,或類似的東西。這沒關係,但似乎有點蠻力。
  3. 我可以註冊一個全局過濾器並處理OnAuthenticate,基本上做同樣的事情。這看起來好一點,但我對這裏的影響不大。
  4. 我可以派生一個基礎控制器,並模擬添加屬性來提供這些信息。這看起來有點「老派」,我討厭爲了一個目的而製作基礎班。
  5. 我可以創建一個緩存靜態方法,它可以獲取第一次訪問的信息。這基本上不比單身更好。
  6. 我也可以創建我自己的IPrincipal,但這意味着每次都會將其轉換爲數據,而且看起來很笨重。我可以將它包裝在另一個類中以簡化它,但仍然...
  7. 我可以將數據存儲在表單身份驗證cookie中,並從那裏獲取它。有一些工具可以使這更容易。

有沒有我沒想過的方法?什麼是「mvc正確」的做法?

+0

非常重要的對我來說問題。 –

回答

5

我認爲最好的方法是使用Cookies。下面是我在my project使用的解決方案:

創建一個類將數據保存在它

[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; 
    } 
} 
1

FormsAuthenticationExtensions項目解決了將附加信息存儲在auth cookie本身中的問題。 http://formsauthext.codeplex.com/

這使備份數據庫命中,並且只要auth cookie存活,因此如果用戶請求「記住我」,它就會起作用。它可以以與標準表單身份驗證相同的方式(在MVC中)使用。

對於你的問題,什麼是MVCisch最多的方式:我會首先決定我想保留哪些信息。問題的這一部分與MVC框架相當獨立,因爲這些概念(會話,發佈數據,cookie等)是在有或沒有它的情況下給出的。

+0

是的,我指的是使用formsauthext時,我提到的工具,使它更容易地存儲在cookie中。 –

1

我將實現並擴展了IPrincipalIIdentity,所以當你訪問User.Identity你會發現姓氏和名字。 這種方式比較好。

對於我的項目,我擴展了IIdentity和IPrincipal以及我的類,添加了我始終需要的「待在那裏」的屬性。對我來說不是這麼大的工作,我的意思是,只有一些方法需要實施。

對於IIdentity,接口要求只有AuthenticationType (string)IsAuthenticated (bool)Name (string)

雖然IPrincipal的Identity (IIDentity)IsInRole (boolean)