ASP.NET会话超时问题

3

我有关于ASP.NET会话的问题。我在网上搜索了一段时间,但无法找到为什么它不起作用的原因。会话在几分钟后消失。这是一个不是由我创建的项目,我不是aspx专家。但是我正在努力解决这个问题。

Web.config

 <system.web>
     <authentication mode="Forms">
        <forms loginUrl="~/Default.aspx" timeout="120" slidingExpiration="true" />
     </authentication>

    <customErrors mode="RemoteOnly"/>
    <httpRuntime requestValidationMode="2.0"/>
    <pages validateRequest="false" />

    <sessionState mode="InProc" cookieless="false" timeout="120"  />

  </system.web>

检查需要登录的页面是否已登录 如果 (!functions.isLoggedIn(Session)) { Response.Redirect("Default.aspx"); } 函数

public static bool isLoggedIn(HttpSessionState session)
        {
            return session["user"] != null;
        }

未登录?显示登录表单,填写表单并将其发送到服务器进行验证。

protected void Page_Load(object sender, EventArgs e)
    { 
       if (Request["do"] != null)
        {
            switch (Request["do"])
            {
                case "logout":
                    Session.Abandon();
                    break;
            }
        }
     if (Request.ServerVariables["REQUEST_METHOD"].ToLower() == "post")
                {
                    //get username en password
                    string username = Request["username"];
                    string password = Request["password"];
                    if (String.IsNullOrWhiteSpace(username) || String.IsNullOrWhiteSpace(password))
                    {
                        LoginMessage.Text = "Please fill in all the fields...";
                    }
                    else
                    {
                        password = FormsAuthentication.HashPasswordForStoringInConfigFile(
                                password,
                                "SHA1");
                            UserService gs = new UserService();
                            user g = gs.getUserByLogin(username, password);
                        if (g == null)
                        {
                            //wrong login
                            LoginMessage.Text = "Invalid username/password.";
                        }
                        else
                        {
                            //good login
                            Session["user"] = g;
                            System.Diagnostics.Debug.WriteLine("timeout:" + Session.Timeout);
                            Response.Redirect("Home.aspx");
                        }
                   }
    }
}

userservice中的GetUserByLogin函数

public user getUserByLogin(string username, string password)
        {
            user g;
            var db = new projectName.Db.Models.projectnetContext();

            IQueryable<user> query = from gb in db.users
                where gb.username.Equals(username)
                      && gb.Passwoord.Equals(password.ToLower())
                      && gb.Status == 1
                select gb;

            if (!query.Any())
                g = null;
            else
                g = query.First();

            return g;
        }

登录后,创建会话

Session["user"] = g;

我的问题是我已经设置了超时时间,但它似乎不起作用。如果我在服务器上检查超时时间,它被设置为120。但是在两分钟后,我会被重定向到登录表单。我能解决这个问题吗?如果我在本地调试,它似乎有效,但在线上不行。

登录功能正常。会话已设置(否则我就无法进入下一页)。如果我转到另一个页面(速度比+-5分钟快),那么我仍然登录。所以这个问题是可重现的。

如果不行,那么使用Cookies呢?通常我在PHP中使用Cookies,..但是在ASP.NET中有一种安全的方法可以做到吗?


我很久以前写了这篇文章,希望它能对你有所帮助... http://aspalliance.com/1182_Troubleshooting_Session_Related_Issues_in_ASPNET - Rahul Soni
根据您的配置,会话值存储在进程中,因此也依赖于w3wp.exe进程。如果应用程序池重新启动,则会话将丢失。 - D4rkTiger
我不确定我是否理解了这个。将项目上传到Web服务器后,我再次登录。但问题仍然存在。自从上传到服务器以来,我没有更改过其他内容。 - Finduilas
4个回答

0
请找到这个MVC控制器动作方法的示例。
    // POST: /Secure/Login
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginFormModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.Login, model.Password))
            {
                using (var db = new DatabaseEntities())
                {
                    var user = db.Users.Single(u => u.Login == model.Login);

                    Membership.UpdateUser(new MembershipUser("UserMembershipProvider", user.Login, null, null, null, null, true, false, DateTime.MinValue, DateTime.Now, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue));

                    #region Create Authentication Cookie

                    Response.Cookies.Add(MyAppFormAuthenticationCookie.Create(user, model.RememberMe));

                    #endregion

                    if (!string.IsNullOrWhiteSpace(returnUrl))
                    {
                        return Redirect(HttpUtility.UrlDecode(returnUrl));
                    }

                    if (model.UserFormType == UserType.Candidate)
                    {
                        return RedirectToAction("Index", "Dashboard", new { area = "Candidate" });
                    }

                    if (model.UserFormType == UserType.Recruiter)
                    {
                        return RedirectToAction("Index", "Dashboard", new { area = "Recruiter" });
                    }

                    if (model.UserFormType == UserType.SuperAdmin || model.UserFormType == UserType.Admin)
                    {
                        return RedirectToAction("Index", "Dashboard", new { area = "Admin" });
                    }
                }
            }

            ModelState.AddModelError("", "Incorrect username and/or password");
            return View("Index", model);
        }

        return RedirectToAction("Index", "Home");
    }

在本示例中,您有:
  • 更新用户配置文件以设置最后连接日期和其他信息(如果需要)...
  • 以自定义方式创建身份验证 cookie,供本示例使用
  • 根据用户类型重定向到首页

那么,在您的应用程序中,您是否有类似的身份验证方法呢?

编辑1:

通常,您必须完成类似于以下的身份验证过程:

        var authTicket = new FormsAuthenticationTicket("MyAuthTicket", rememberMe, timeout: 120);
        var encryptAuthTicket = FormsAuthentication.Encrypt(authTicket);
        Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encryptAuthTicket) { Expires = authTicket.Expiration });

我验证用户的那部分在第三个代码块(全局职位)中。我没有更多了吗? - Finduilas
但是身份验证不能仅仅是针对数据库对象的登录/密码检查。您必须保留身份验证令牌,并且这必须通过FormsAuthentication完成。请参见EDIT1。 - D4rkTiger
那么我不使用身份验证,这样做对吗?我所做的唯一一件事就是将g存储在会话用户中,并且我还使用FormsAuthentication.HashPasswordForStoringInConfigFile。 - Finduilas
是的,你验证了用户,但你没有给他一个可以证明他身份验证的票据。这样做可能能够工作,但不安全且不可靠。是的,我看到你使用了FormsAuthentication.HashPasswordForStoringInConfigFile,但正如你在MSDN文档中所读到的(https://msdn.microsoft.com/fr-fr/library/system.web.security.formsauthentication.hashpasswordforstoringinconfigfile%28v=vs.110%29.aspx),它并不是用来验证用户身份的,而只是像你可能已经做过的那样加密密码来注册用户。 - D4rkTiger
好的,我会阅读文档,尝试在未来几天内实现。 - Finduilas

0

嗯,我建议你在ASP.NET中使用Profile而不是Session。


0

我已经在 web.config 中使用了身份验证。现在我把它添加到全局文章中。这个超时时间也被设置为120。 - Finduilas
1
好的,但是你如何验证用户?你还没有发布任何代码来说明你是如何做到的...你能发布这段代码吗? - D4rkTiger
我添加了一些额外的代码。在填写登录表单后会发生什么......仍然有些东西丢失吗? - Finduilas
1
我会发布一个使用表单身份验证的POC项目示例,以说明我试图向您解释的内容;-) - D4rkTiger

-2

仅仅是一个建议...你是否有任何重定向(Response.Redirect)到不同的站点或者试图访问你没有权限的资源?在这些情况下,会话将会过期。


是的,我有重定向(在检查用户是否已登录(=会话设置)之后)。但是它是到同一站点的页面,即登录表单页面(=default.aspx)。 - Finduilas
如果你正在使用 Response.Redirect,你能否将它改为 Server.Transfer 并尝试一下? - redsam
嗯,正如您在全局帖子中所看到的那样,只有在检查会话后才能进行操作。而不是之前。--> functions.isLoggedIn(Session)。 - Finduilas
即使响应重定向到另一个网站,会话也不会丢失,因为会话已附加到服务器上,所以不能丢失,因为用户关闭他的浏览器。;-) - D4rkTiger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接