Question

J'ai une application MVC où j'ai une classe utilisateur et l'utilisateur peut également usurper l'identité d'un autre utilisateur (Administrateurs uniquement).

J'ai donc ce code ci-dessous qui authentifie la demande et instancie ma version d'une classe utilisateur.

Il tente alors d'obtenir l'utilisateur personnifié de l'objet de la session, mais la session n'est pas disponible dans cette méthode dans le global.asax.

Espérons que cela fait sens.

Comment pourrais-je faire?

Ma question je pense est à quel point les méthodes de global.asax vous avez accès à l'objet de la session pour chaque demande?

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

Pas de solution correcte

Autres conseils

Essayez de créer un filtre d'autorisation:

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

Vous pouvez ensuite appliquer cet attribut à vos contrôleurs. Idéalement, vous auriez un contrôleur de base que tous les autres contrôleurs héritent et vous pouvez appliquer l'attribut au niveau de la classe sur ce contrôleur. Alors toutes vos demandes seraient autorisés et appliquer le usurpation d'identité que vous avez un code ci-dessus.

session ne sera pas disponible pendant AuthenticateRequest: Ce que vous devez faire est de balise les informations nécessaires à la Identity.userData; Ainsi, par exemple si vous utiliseriez l'authentification des formulaires procédez comme suit:

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"
     }
   }
}

Pour connecter à l'aide des formulaires que vous aurez besoin d'écrire un cookie personnalisé: MVC -> Classe FormsAuthenticationService: 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);
}

Enfin, dans SignIn vous maintenant créer le ticket nécessaire en appelant CreateTicket (...), puis vous l'écrire par 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);
    }
}

Je ne l'ai jamais utilisé, mais supposons que l'état de session est attribué au cours de la AcquireRequestState:

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

J'ai eu cette même question d'avoir besoin d'accéder à la session en global.asax et finalement résolu en déplaçant mon code dans le gestionnaire de AcquireRequestState, ce qui arrive après l'authentification est passée.

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

Ce bouton déclenche beaucoup et le contexte actuel ne dispose pas toujours d'un objet de session valide, d'où le chèque.

EDIT : Nous avons dû ajouter le chèque IsAuthenticated aussi - une erreur devenait nulle lorsque déconnecté. Fonctionne très bien maintenant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top