2011-09-02 10 views
10

Ok, esto parece ser una necesidad común. Un poco de google encuentra muchas formas de hacer esto. Estoy interesado en la forma más "correcta de mvc" para hacerlo.Cómo inicializar información sobre la autorización

Tengo, en la esquina superior derecha de mi aplicación, un saludo que dice Hello FirstName LastName. Ahora, es bastante fácil acceder al nombre de usuario del usuario que inició sesión, a través del IPrincipal (también conocido como User.Identity.Name). Sin embargo, esto no me dará el nombre y apellido del usuario. Tengo que presionar la API de membresía para obtener eso.

Al golpear la API de membresía tiene sus inconvenientes. Llega a la base de datos todo el tiempo, lo que agrega un acceso de acceso adicional a cada página servida. Es bastante fácil establecer algunas variables de sesión al iniciar sesión, pero esto solo funciona para esa sesión. Si el usuario hace clic en "Recordarme", no se iniciará la sesión la próxima vez y aún tengo que cargar estos valores.

  1. Pude crear mi propio proveedor de membresía para hacer algo de caché, pero eso es mucho trabajo para un propósito más o menos único.
  2. Podría usar Application_AuthenticateRequest y presionar la API de membresía y almacenar los valores en variables de sesión, o algo similar. Esto está bien, pero parece un poco de fuerza bruta.
  3. Pude registrar un filtro global y manejar OnAuthenticate, esencialmente haciendo lo mismo. Esto parece un poco mejor, pero estoy fuera de las ramificaciones aquí.
  4. Podría obtener un controlador de base, y simplemente agregar propiedades para proporcionar esta información. Esto parece un poco "old school", y odio tener que hacer una clase base con un solo propósito.
  5. Pude crear un método estático de caché que obtendría la información en el primer acceso. Esto básicamente no es mucho mejor que un singleton.
  6. También podría crear mi propio IPrincipal, pero eso significa lanzarlo cada vez para obtener los datos, y eso parece torpe. Podría incluirlo en otra clase para simplificarlo, pero aún así ...
  7. Podría almacenar los datos en la cookie de autenticación de formularios, y obtenerlos desde allí. Hay algunas herramientas disponibles para que sea más fácil.

¿Hay algún método que no haya pensado? ¿Y cuál es la forma más "correcta de mvc" de hacerlo?

+0

pregunta muy importante para mí también. –

Respuesta

5

Creo que la mejor manera es utilizando cookies.Aquí está la solución que utilicé en my project:

Crear una clase para guardar datos en él

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

Signin método:

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

authCookie Marco:

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); 
} 

Conseguir 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; 
} 

En 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

El proyecto FormsAuthenticationExtensions resuelve este problema almacenando la información adicional en la cookie de autenticación. http://formsauthext.codeplex.com/

Esto ahorra el golpe de la base de datos, y vive tanto como la cookie de autenticación, por lo tanto, funciona si los usuarios piden "recordarme". Se puede usar de la misma manera (en MVC también) que la autenticación de formularios estándar.

Para su pregunta, ¿cuál es la forma más MVCisch: primero decidiría dónde quiero guardar la información. Esta parte de la pregunta es bastante independiente del marco de MVC ya que los conceptos (sesión, datos de publicación, cookies, etc.) se dan con o sin él.

+0

Sí, me refería a usar formsauthext cuando mencioné herramientas para facilitar el almacenamiento en la cookie. –

1

voy a implementar y ampliar la IPrincipal y IIdentity, por lo que cuando se accede a User.Identity encontrará Apellidos y FirstName. De esta manera es mejor imo.

Para mis proyectos he ampliado IIdentity e IPrincipal con mis clases agregando las propiedades que siempre necesito "estar allí". Para mí no es un gran trabajo, quiero decir, solo hay un montón de métodos que deben implementarse.

Para IIdentity, el requisito de interfaz es solo AuthenticationType (string), IsAuthenticated (bool) y Name (string).

Mientras que en IPrincipal Identity (IIDentity) y IsInRole (boolean)

Cuestiones relacionadas