Pregunta

Tengo una aplicación MVC en el que tengo una clase de usuario y el usuario también puede hacerse pasar por otro usuario (usuarios administradores solamente).

Así que tengo este código de abajo que autentica la solicitud y crea una instancia mi versión de una clase de usuario.

A continuación, tratar de que el usuario representado por el objeto de sesión, pero la sesión no está disponible en este método en el Global.asax.

Espero que esto tiene sentido.

¿Cómo podría yo hacer esto?

Mi pregunta supongo que es en qué punto los métodos Global.asax hace, tendrá acceso a objeto Session para cada petición?

protected void Application_OnAuthenticateRequest(object sender, EventArgs e)
{
    IMylesterService service = ObjectFactory.GetInstance<IMylesterService>();

    if (Context.User != null)
    {
        if (Context.User.Identity.IsAuthenticated)
        {
            User user = service.GetUser(Context.User.Identity.Name);
            if (user == null)
                throw new ApplicationException("Context.user.Identity.name is not a recognized user");

            User impersonatedUser = (User)this.Session["ImpersonatedUser"];
            if (impersonatedUser == null)
                user.ImpersonatedUser = user;
            else
                user.ImpersonatedUser = impersonatedUser;

            System.Threading.Thread.CurrentPrincipal = Context.User = user;
            return;
        }
    }
    User guest = service.GetGuestUser();
    guest.ImpersonatedUser = guest;

    System.Threading.Thread.CurrentPrincipal = Context.User = guest;
}

No hay solución correcta

Otros consejos

Trate de crear un filtro de autorización:

public class CustomAuthorizationFilter : AuthorizeAttribute
{
    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        // perform your authorization here
        // full access to HttpContext and session
    }
}

A continuación, puede aplicar este atributo a los controladores. Lo ideal sería que tendría un controlador de base que todos los demás controladores heredan de y se podía aplicar el atributo a nivel de clase en ese controlador. Entonces todas sus peticiones serían autorizados y aplicar la suplantación como ha codificado anteriormente.

La sesión no estará disponible durante AuthenticateRequest: Lo que usted necesita hacer es etiqueta de la información necesaria para la Identity.userData; así por ejemplo, si en el uso de la autenticación de formularios haga lo siguiente:

void Application_AuthenticateRequest(object sender, EventArgs e)
{
   if (Context.User != null)
   {
     if (Context.User.Identity.IsAuthenticated)
     {
       // retrieve the value 
       var id = (FormsIdentity)Context.User.Identity;
       var myvalue = id.Ticket.UserData; // "Here you are"
     }
   }
}

Para la muestra en el uso de formularios que hay que escribir una cookie personalizado: MVC -> FormsAuthenticationService clase: IFormsAuthenticationService

public static void SetAuthenticationCookie(HttpContextBase context, FormsAuthenticationTicket ticket)
{
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName)
       {
          Value = FormsAuthentication.Encrypt(ticket),
          Secure = FormsAuthentication.RequireSSL,
          Domain = FormsAuthentication.CookieDomain,
          HttpOnly = true,
          Expires = DateTime.Now.AddMinutes(15)
       };

    if (!context.Request.IsSecureConnection && FormsAuthentication.RequireSSL)
    {
        throw new HttpException("Ticket requires SSL.");
    }
    context.Response.Cookies.Add(cookie);
}
public static FormsAuthenticationTicket CreateTicket(HttpContextBase context, string emailAddress, string userData, bool persist)
{
    return new FormsAuthenticationTicket(1, emailAddress, DateTime.Now, DateTime.Now.AddMinutes(15), persist, userData, FormsAuthentication.FormsCookiePath);
}

Finalmente en SignIn que sería crear ahora el billete requerido llamando CreateTicket (...), y luego se escribirían a cabo por SetAuthenticationCookie (...).

public void SignIn(string userName, string password)
{
    if(CheckUserValid(userName,password, out string email))
    {
        var ticket = CreateTicket(email, "Here you are", true);
        SetAuthenticationCookie(HttpContext.Current.Base(), ticket);
    }
}

nunca he usado, pero suponer que se asigna el estado de sesión durante el AcquireRequestState:

public void Init(HttpApplication context)
{
    context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}

Tuve este mismo problema de necesitar sesión de acceso en global.asax y finalmente lo resolvió moviendo mi código en el controlador de AcquireRequestState, lo que sucede después de que se aprobó la autenticación.

    protected void Application_AcquireRequestState(Object sender, EventArgs e)
    {
        if (Request.IsAuthenticated && Context.Session != null)
        {
            // access Context.Session
        }
    }

Este incendios mucho y el contexto actual no siempre tiene un objeto de sesión válida, por lo tanto, el cheque.

Editar : Tuvo que añadir el cheque por IsAuthenticated también - era conseguir un error nulo cuando la sesión. Funciona muy bien ahora.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top