【问题标题】:Session object is null after some time in ASP.NET MVC 4会话对象在 ASP.NET MVC 4 中一段时间​​后为空
【发布时间】:2014-05-02 08:46:45
【问题描述】:

我有 Web 应用程序 ASP.NET MVC 4。当用户登录到应用程序时,我将他的信息作为 UserCtx 类的对象写入会话。之前,我创建了一个 cookie:

public ActionResult executeLogin(LoginModel model)
{
        if (ModelState.IsValid)
            {
                FormsAuthentication.SetAuthCookie(model.UserName, false);

                UserCtx userCtx = ds.SetUserCtx(model.UserName, model.Password);
                Session["UserCtx"] = userCtx;
                return Redirect(returnUrl ?? "/Offer");
            }
        else
            {
                return View("Index");
            }
    }

为了更容易操作会话中持有的对象,我创建了一个静态属性,我在应用程序中使用它:

public class UserCtx
{
    public static UserCtx UserLogged 
    {
        get
        {
            UserCtx userCtx = ((UserCtx)HttpContext.Current.Session["UserCtx"]);
            return userCtx;
        }
    }

}

例如我经常在视图中使用这个属性:

@if (UserCtx.UserLogged.ADMIN)
{
   @Html.Partial("_gvNetLogPartial")
}

然而,一段时间后,这个变量为空,但我真的不知道为什么会这样。此外,我在 web.config 中设置了超时:

<sessionState timeout="30"/>

另外,我在每个控制器上都有过滤器来检查会话的值。这是过滤器:

public class CheckSessionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Session["UserCtx"] == null)
        {
            FormsAuthentication.RedirectToLoginPage();
        }
    }
}

这个错误可能是因为我使用了静态属性?

【问题讨论】:

    标签: asp.net-mvc-4 session session-variables session-state session-timeout


    【解决方案1】:

    最近我开发了一个 Web .NET 应用程序,我将有关当前登录用户的信息存储到一个“静态”Session 对象中,就像您的代码一样。

    但是,我意识到这是一种老式的方法,与旧的 ASP 一起使用。现在,ASP.NET 提供了一种更好的方式来处理用户对象。

    您应该将标准User 对象覆盖为HttpContext,而不是使用Session 对象。我按照这种方法替换了我的代码,并且效果很好。

    下面,我将回顾一下我所做的步骤 - 我建议你也这样做。

    首先,您必须编写一个类来存储您需要的有关用户的信息。这是我的。

    public interface ICustomPrincipal : IPrincipal
    {
        string Email { get; set; }
        string[] Roles { get; set; }
        int[] SalesmenId { get; set; }
        bool HasWritePermission { get; set; }
    }
    
    public class CustomPrincipalSerializeModel
    {
        public string Email { get; set; }
        public string[] Roles { get; set; }
        public int[] SalesmenId { get; set; }
        public bool HasWritePermission { get; set; }
    }
    
    public class CustomPrincipal : ICustomPrincipal
    {
        private IPrincipal principal;
    
        public CustomPrincipal(IPrincipal principal, WindowsIdentity identity)
        {
            this.Identity = identity;
            this.principal = principal;
        }
    
        public IIdentity Identity { get; private set; }
    
        public bool IsInRole(string role)
        {
            //return (principal.IsInRole(role));
            if (Roles == null)
                return false;
            return Roles.Contains(role);
        }
    
        public string Email { get; set; }
    
        public string[] Roles { get; set; }
    
        public int[] SalesmenId { get; set; }
    
        public bool HasWritePermission { get; set; }
    }
    

    然后,编辑 Global.asax,以便在用户登录后,将当前 HttpContextUser 对象替换为您在上一步中定义的自定义类型的对象(参见非常最后一条指令)。

        protected void WindowsAuthentication_OnAuthenticate(Object source, WindowsAuthenticationEventArgs e)
        {
            if (e.Identity.IsAuthenticated && null == Request.Cookies.Get(CookieName))
            {
                CustomPrincipalSerializeModel cp = new CustomPrincipalSerializeModel();
    
                string username = e.Identity.Name;
    
                [...]
    
                // Set the data of the current user
                cp.Roles = [...];
                cp.SalesmenId = [...];
                cp.Email = [...];
                cp.HasWritePermission = [...];
    
                [...]
    
                // Serialize the cookie
                JavaScriptSerializer jss = new JavaScriptSerializer();
                string userData = jss.Serialize(cp);
                FormsAuthenticationTicket formsAuthTicket =
                    new FormsAuthenticationTicket(
                                1,
                                username,
                                DateTime.Now,
                                DateTime.Now.AddHours(10), // The cookie will expire in 10 hours
                                false,
                                userData);
                var encryptedTicket = FormsAuthentication.Encrypt(formsAuthTicket);
    
                // Store the cookie
                HttpCookie httpCookie = new HttpCookie(CookieName, encryptedTicket);
                Response.Cookies.Add(httpCookie);
            }
        }
    
        protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            CustomPrincipal newUser = new CustomPrincipal(User, (WindowsIdentity)User.Identity);
    
            HttpCookie authCookie = Context.Request.Cookies.Get(CookieName);
    
            if (authCookie != null)
            {
                FormsAuthenticationTicket formsAuthenticationTicket = FormsAuthentication.Decrypt(authCookie.Value);
    
                JavaScriptSerializer jss = new JavaScriptSerializer();
    
                CustomPrincipalSerializeModel ret = jss.Deserialize<CustomPrincipalSerializeModel>(formsAuthenticationTicket.UserData);
                newUser.Email = ret.Email;
                newUser.Roles = ret.Roles;
                newUser.SalesmenId = ret.SalesmenId;
                newUser.HasWritePermission = ret.HasWritePermission;
            }
            else
            {
                newUser.Email = null;
                newUser.Roles = null;
                newUser.SalesmenId = null;
                newUser.HasWritePermission = false;
            }
    
            Context.User = Thread.CurrentPrincipal = newUser;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 2015-01-14
      • 1970-01-01
      相关资源
      最近更新 更多