2011-09-02 95 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)