Pergunta

Eu tenho um aplicativo MVC em que tenho uma classe de usuário e o usuário também pode se passar por outro usuário (somente usuários do administrador).

Então, eu tenho esse código abaixo que autentica a solicitação e instancia minha versão de uma classe de usuário.

Em seguida, ele tenta obter o usuário personalizado do objeto da sessão, mas a sessão não está disponível neste método no global.asax.

Espero que isso faça sentido.

De que outra forma eu poderia fazer isso?

Minha pergunta, acho que está em que momento nos métodos globais.ASAX você obtém acesso ao objeto de sessão para cada solicitação?

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

Nenhuma solução correta

Outras dicas

Tente criar um filtro de autorização:

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

Você pode aplicar esse atributo aos seus controladores. Idealmente, você teria um controlador base que todos os outros controladores herdam e aplicar o atributo no nível da classe nesse controlador. Em seguida, todas as suas solicitações seriam autorizadas e aplicariam a representação como você codificou acima.

A sessão não estará disponível durante o AuthenticateRequest: o que você precisará fazer é marcar as informações necessárias para a identidade.UserData; Por exemplo, se você estiver usando a autenticação de formulários, faça o seguinte:

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 entrar em uso usando formulários, você precisará escrever um cookie personalizado: 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);
}

Finalmente, na assinatura, agora você criaria o ticket exigido ligando para CreateTicket (...) e, em seguida, você o escreveria 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);
    }
}

Eu nunca o usei, mas suponho que o estado da sessão seja atribuído durante o adquirereQuestState:

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

Eu tive a mesma questão de precisar acessar a sessão em global.asax e finalmente resolvi a movendo meu código para o AcquireRequestState Handler, que acontece após a aprovação da autenticação.

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

Isso dispara muito e o contexto atual nem sempre possui um objeto de sessão válido, daí a verificação.

EDITAR: Tinha que adicionar a verificação para isauthenticated também - estava recebendo um erro nulo quando logado. Funciona muito bem agora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top