ASP.NET MVC: autenticarse una vez y solo una vez hasta que finalice la sesión

Preparar

Estoy usando la autenticación de formularios personalizada, todo lo estándar.

En la acción de inicio de sesión en mi controlador de cuenta,

  • Verifico los detalles del usuario contra el db
  • Si tengo éxito, creo un ticket de autenticación de formularios
  • Almacene la identificación de la fila de la base de datos de los miembros registrados en UserData en el ticket
  • Cifrar el boleto
  • Guarda el billete en una cookie
  • Agregue las cookies a la colección Response.Cookies
  • Redirigir a la acción de índice en el controlador de inicio

Registré un controlador en asax global para el evento AuthenticateRequest. En mi controlador,

  • Recupero la cookie de HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
  • Si la cookie existe, descifro el valor del ticket de autenticación de formularios en la cookie
  • Recupere los detalles del usuario de la base de datos usando la identificación almacenada en el ticket de autenticación UserData.
  • Cree un principal personalizado y establezca el usuario (tiene una propiedad LoggedInUser personalizada) en el usuario que recuperé de la base de datos.
  • Establezca HttpContext.Current.User en el principal personalizado

Problema

Depuro una solicitud para la página de inicio después de haber iniciado sesión y observo que el controlador AuthenticateRequest en global.asax se activa más de una vez por solicitud de página. Revisé HttpContext.Current.Request.Path y esto se debe a que cada recurso en mi página (efectivamente, cada HTTP GET) está activando la solicitud de autenticación, entonces, GET jquery.js, GET logo.png, etc.

Pregunta

En el primer AuthenticateRequest manejado, voy a la base de datos y luego configuro HttpContext.Current.User en mi principal personalizado. ¿Cuál sería una buena manera de evitar ir a la base de datos para obtener HTTP GET posteriores que hacen que se active AuthenticatRequest? Efectivamente, autentíquese una vez y solo una vez hasta que el usuario cierre su navegador o hasta que caduque el Ticket de Autenticación.

TIA

preguntado el 12 de junio de 12 a las 17:06

1 Respuestas

En lugar de usar el AuthenticateRequest en su Global.asax, le recomendaría escribir un filtro de acción global. De esta manera, el filtro de acción se aplicará solo antes de ejecutar alguna acción y poblar el Usuario. De hecho una costumbre [Authorize] El atributo es la mejor manera de lograr eso:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }

        // TODO: go ahead and work with the UserData from the authentication cookie
        // basically all the steps you described for your AuthenticateRequest handler
        // except for checking the presence of the forms authentication cookie because
        // we know that at this stage it exists and the user was successfully authorized

        return true;
    }
}

Respondido el 12 de junio de 12 a las 17:06

Esta es una buena solución, siempre que el usuario no necesite proporcionar autorización a recursos individuales (como fotos, archivos PDF u otros archivos a los que el usuario quiera controlar el acceso). - Erik Funkenbusch

Esos recursos normalmente se deben servir a través de una acción de controlador y, por lo tanto, recurrir al proceso de autorización estándar de ASP.NET MVC. - darin dimitrov

No necesariamente, uno podría usar una ubicación web.config, por ejemplo. Sin embargo, dado que la autenticación se realiza en el nivel de acción, no habrá ninguna autorización en el nivel global. Que puede estar bien. Solo quiero señalar que este enfoque solo es válido si solo está asegurando las acciones del controlador. - Erik Funkenbusch

Personalmente nunca uso el <location> elemento en mis aplicaciones ASP.NET MBVC para realizar la autenticación y autorización. - darin dimitrov

Esta es una forma interesante de realizar la Autenticación y Autorización. Nunca he considerado esto, pero estoy investigando ahora. Habría seguido automáticamente la ruta Global.Authenticate_Request. Me he encontrado con este artículo (blogs.msdn.com/b/rickandy/archive/2011/05/02/…) que me parece bastante útil. Darin, actualizaré mi solución con tu sugerencia y prueba y luego publicaré más comentarios. gracias por tu sugerencia... siempre es bueno aprender algo nuevo. - alan alcock

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.