NullReferenceException in User Filter

0

In my project I made a filter to see if the user is already logged in. To prevent it from logging in twice.

According to the answer

What happens is that I am having a zero reference error and I do not know why. I am passing the ID of the user in the session, but I am not able to capture it at the time of doing this check, generating me this error:

  

Description: An unhandled exception occurred during the execution of the current Web request. Examine the stack trace for more information about the error and where it originated in the code.

     

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

And the error is being generated on this line:

var idDoUsuario = (long) filterContext.HttpContext.Session["UsuarioID"];  

At the level of more information, I'll put the class codes I use for the filter and the action that I use to authenticate.

Filter

 void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        var contexto = new EntidadesContexto();
        // Recupero a Id do Usuário logado aqui.
        // Não sei como você está fazendo, então inventei um método
        var idDoUsuario = (long) filterContext.HttpContext.Session["UsuarioID"];           

        var usuario = contexto.Usuarios.FirstOrDefault(u => u.UsuarioID == idDoUsuario && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);

        if (usuario != null)
        {
            // Se o último login foi feito dentro do período de um dia
            if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
            {
                // Usuário logado em outro lugar.
                usuario.Logado = false;
                contexto.Entry(usuario).State = EntityState.Modified;
                contexto.SaveChanges();
                // Destrua aqui a Session do Usuário se houver uma.                    
            }
            else
            {
                filterContext.HttpContext.Session.Abandon();
                // O login do Usuário expirou.
                var controller = (MeuControllerBase)filterContext.Controller;                    
                filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
            }
        }

Authentication

 [FiltroSessao]
    [HttpPost]       
    public ActionResult Index(String Login, String Senha)
    {
        //verificando login pelo usuario do banco de dados ...
        Usuario login = db.Usuarios.Where(x => x.Login == Login && x.Senha == Senha).FirstOrDefault();
        if (login != null)
        {
            FormsAuthentication.SetAuthCookie(login.Nome.ToString(), false);
            Session.Add(".PermissionCookie", login.Perfil);
            Session.Add("UsuarioID", login.UsuarioID);

            login.Logado = true;
            login.UltimoLogin = DateTime.Now;
            login.SessionID = HttpContext.Session.SessionID;

            db.Entry(login).State = EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index", "Home"); //pagina padrao para todos os usuarios...
        }
        return RedirectToAction("Index");

    }

Just to highlight, I pass the ID of the user in this line:

Session.Add("UsuarioID", login.UsuarioID);

Any suggestions?

    
asked by anonymous 01.12.2014 / 21:22

2 answers

0

As I researched, and from what I saw of your code, [FiltroSessao] is running before you set the Session value. There are two ways to resolve:

  • Change from:

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    

    To:

    void IActionFilter.OnActionExecuted(ActionExecutingContext filterContext)
    
  • Make FiltroSessao receive parameters:

    namespace SeuProjeto.Filters 
    {
        public class UniqueSessionActionFilter : ActionFilterAttribute, IActionFilter
        {
            public long UsuarioId { get; set; }
    
            void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
            {
                var contexto = new EntidadesContexto();
                // Recupero a Id do Usuário logado aqui.
                var idDoUsuario = UsuarioId;     
    
                var usuario = contexto.Usuarios.FirstOrDefault(u => u.UsuarioID == idDoUsuario && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);
    
                if (usuario != null)
                {
                    // Se o último login foi feito dentro do período de um dia
                    if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
                    {
                        // Usuário logado em outro lugar.
                        usuario.Logado = false;
                        contexto.Entry(usuario).State = EntityState.Modified;
                        contexto.SaveChanges();
                        // Destrua aqui a Session do Usuário se houver uma.                    
                    }
                    else
                    {
                        filterContext.HttpContext.Session.Abandon();
                        // O login do Usuário expirou.
                        var controller = (MeuControllerBase)filterContext.Controller;                    
                        filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
                    }
                }
            }
        }
    }
    

    Usage:

    public class ControllerExemplo 
    {
    
        public long ExemploUsuarioId { get; set; }
    
        public ControllerExemplo() {
            ExemploUsuarioId = HttpContext.Current.Session["UsuarioID"]);
        }
    
        [FiltroSessao(UsuarioId = ExemploUsuarioId)]
        public ActionResult Index() { ... }
    }
    
02.12.2014 / 03:23
1

From what I saw in your code, you maintain a session with the ID of User just to recover in filter . Could not recover User from UserName ? That way you would not have to manipulate a Session.

You get the userName of the user logged in by accessing filterContext.HttpContext.User.Identity.Name . If you need to test if the User is logged in you can check the value of filterContext.HttpContext.User.Identity.IsAuthenticated ;

void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        var contexto = new EntidadesContexto();

        var userName = filterContext.HttpContext.User.Identity.Name;           

        // estou assumindo que seu objeto Usuario possui a property UserName
        var usuario = contexto.Usuarios.FirstOrDefault(u => u.UserName == userName && u.Logado && u.SessionID != filterContext.HttpContext.Session.SessionID);

        if (usuario != null)
        {
            // Se o último login foi feito dentro do período de um dia
            if (usuario.UltimoLogin.AddDays(1) > DateTime.Now)
            {
                // Usuário logado em outro lugar.
                usuario.Logado = false;
                contexto.Entry(usuario).State = EntityState.Modified;
                contexto.SaveChanges();
                // Destrua aqui a Session do Usuário se houver uma.                    
            }
            else
            {
                // O login do Usuário expirou.
                var controller = (MeuControllerBase)filterContext.Controller;                    
                filterContext.Result = controller.RedirectToAction("Index", "Autenticacao");                   
            }
        }
    
02.03.2015 / 15:47