ASP.NET MVC: establezca IIdentity personalizado o IPrincipal



3 Answers

No puedo hablar directamente para ASP.NET MVC, pero para ASP.NET Web Forms, el truco es crear un FormsAuthenticationTicket y encriptarlo en una cookie una vez que el usuario haya sido autenticado. De esta forma, solo tiene que llamar a la base de datos una vez (o AD o lo que sea que esté utilizando para realizar su autenticación), y cada solicitud subsiguiente se autenticará en base al ticket almacenado en la cookie.

Un buen artículo sobre esto: http://www.ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html (enlace roto)

Editar:

Como el enlace anterior está roto, recomendaría la solución de LukeP en su respuesta anterior: share - También sugeriría que la respuesta aceptada se cambie a esa.

Editar 2: una alternativa para el enlace roto: https://web.archive.org/web/20120422011422/http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html

Question

Necesito hacer algo bastante simple: en mi aplicación ASP.NET MVC, quiero establecer un IIdentity / IPrincipal personalizado. Cualquiera que sea más fácil / más adecuado. Quiero extender el valor predeterminado para que pueda llamar a algo como User.Identity.Id y User.Identity.Role . Nada lujoso, solo algunas propiedades extra.

He leído toneladas de artículos y preguntas, pero siento que lo estoy haciendo más difícil de lo que realmente es. Pensé que iba a ser fácil. Si un usuario inicia sesión, quiero configurar un IIdentity personalizado. Así que pensé, implementaré Application_PostAuthenticateRequest en mi global.asax. Sin embargo, eso se invoca en cada solicitud, y no quiero hacer una llamada a la base de datos en cada solicitud que solicitaría todos los datos de la base de datos y colocaría un objeto IPrincipal personalizado. Eso también parece muy innecesario, lento y en el lugar equivocado (hacer llamadas a la base de datos allí), pero podría estar equivocado. ¿O de dónde más provendrían esos datos?

Así que pensé, cada vez que un usuario inicia sesión, puedo agregar algunas variables necesarias en mi sesión, que agrego a la identificación personalizada en el controlador de eventos Application_PostAuthenticateRequest . Sin embargo, mi Context.Session es null , así que tampoco es el camino a seguir.

He estado trabajando en esto por un día y siento que me estoy perdiendo algo. Esto no debería ser demasiado difícil de hacer, ¿verdad? También estoy un poco confundido por todas las cosas (semi) relacionadas que vienen con esto. MembershipProvider , MembershipUser , RoleProvider , RoleProvider , IPrincipal , IIdentity , FormsAuthentication .... ¿Soy el único que encuentra todo esto muy confuso?

Si alguien pudiera decirme una solución simple, elegante y eficiente para almacenar datos adicionales en un IIdentity sin toda la fuzz extra, ¡sería genial! Sé que hay preguntas similares en SO, pero si la respuesta que necesito está allí, debo haberla pasado por alto.




MVC le proporciona el método OnAuthorize que se cuelga de sus clases de controlador. O bien, podría usar un filtro de acción personalizado para realizar la autorización. MVC lo hace bastante fácil de hacer. Publiqué una publicación de blog sobre esto aquí. http://www.bradygaster.com/post/custom-authentication-with-mvc-3.0




Basado en la respuesta de LukeP , y agregue algunos métodos para configurar el timeout y requireSSL cooperó con Web.config .

Los enlaces de referencias

Códigos modificados de LukeP

1, Web.Config el timeout basado en Web.Config . FormsAuthentication.Timeout obtendrá el valor de tiempo de espera, que se define en web.config. Envolví a los seguidores para que sean una función que devuelve un ticket .

int version = 1;
DateTime now = DateTime.Now;

// respect to the `timeout` in Web.config.
TimeSpan timeout = FormsAuthentication.Timeout;
DateTime expire = now.Add(timeout);
bool isPersist = false;

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
     version,          
     name,
     now,
     expire,
     isPersist,
     userData);

2, configure la cookie para que sea segura o no, en función de la configuración de RequireSSL .

HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
// respect to `RequreSSL` in `Web.Config`
bool bSSL = FormsAuthentication.RequireSSL;
faCookie.Secure = bSSL;



Como complemento del código LukeP para usuarios de formularios web (no MVC) si desea simplificar el acceso en el código subyacente de sus páginas, simplemente agregue el código siguiente a una página base y obtenga la página base en todas sus páginas:

Public Overridable Shadows ReadOnly Property User() As CustomPrincipal
    Get
        Return DirectCast(MyBase.User, CustomPrincipal)
    End Get
End Property

Entonces, en su código detrás, simplemente puede acceder a:

User.FirstName or User.LastName

Lo que me falta en un escenario de Web Form, es cómo obtener el mismo comportamiento en código no vinculado a la página, por ejemplo, en httpmodules si siempre agrego un elenco en cada clase o ¿hay alguna manera más inteligente de obtener esto?

Gracias por sus respuestas y gracias a LukeP ya que utilicé sus ejemplos como base para mi usuario personalizado (que ahora tiene User.Roles , User.Tasks , User.HasPath(int) , User.Settings.Timeout y muchas otras cosas agradables)




Related