ASP.NET MVC3表单身份验证过早到期

时间:2016-09-22 15:18:27

标签: c# asp.net-mvc-3 authentication cookies forms-authentication

我们有一个使用MVC3构建的在线评估平台。它在IIS上运行在运行Windows Server 2012 R2的单个专用服务器上运行,我们可以完全控制它。最近,用户一直在报告他们在评估期间“正在退出”。这是一个问题,因为我们的许多评估都有时间限制,并且会记录成本用户宝贵的秒数。

我在测试过程中无法复制该问题,但已通过查阅我们的日志确认过去2个月内~15-20%的用户在评估期间必须重新登录。在此之前的10个月内,只有<2%的人不得不重新登录。

我已将当前的代码库与3个月前的代码库进行了比较,并且没有任何与登录和身份验证相关的任何内容也发生了变化。据我所知,服务器上没有任何设置被更改。

这个应用程序中有数百个文件和数千行代码,但我会尝试分享相关内容,希望有人可以帮我解决这个问题。如果有任何我错过的信息,请发表评论,我会尽快添加。

来自Web.config:

<authentication mode="Forms">
  <forms loginUrl="~/Login/" timeout="300" slidingExpiration="true" />
</authentication>

这是我们创建auth cookie的方式:

Guid User_Id = /* lookup id with username after verification */
string User_Role = /* CSV specifying the roles the user has */
DateTime Expiry = DateTime.Now.AddHours(5);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, User_Id.ToString(), DateTime.Now, Expiry, false, User_Role, "/");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
cookie.Expires = Expiry; 
HttpContext.Current.Response.Cookies.Add(cookie);

我们使用AuthorizeAttribute的自定义实现来限制对大多数操作的访问:

public class MyController : Controller
{
    [CustomAuthorize(Roles = "MyRole")]
    public ActionResult MyAction()
    {
        // do some stuff
        return View();
    }
}

其定义如下:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string cookieName = FormsAuthentication.FormsCookieName;

        if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
            filterContext.HttpContext.Request.Cookies == null ||
            filterContext.HttpContext.Request.Cookies[cookieName] == null
        )
        {
            HandleUnauthorizedRequest(filterContext);
            return;
        }

        var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
        var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        string[] roles = authTicket.UserData.Split(',');

        var userIdentity = new GenericIdentity(authTicket.Name);
        var userPrincipal = new GenericPrincipal(userIdentity, roles);

        filterContext.HttpContext.User = userPrincipal;
        base.OnAuthorization(filterContext);
    }
}

这是过去3年的设置,而且过去2个月一直存在问题。如您所见,cookie设置为在创建后5小时到期。用户通常对他们的报告非常模糊,并且查看我们的日志,初始登录和不得不再次登录之间的时间范围从几分钟到几个小时之间。即便如此,我已经在服务器上查看了我认为相关的设置,并且看不到任何可能导致问题的事情:

IIS Settings

我能想到的唯一一个会导致它们“被注销”的将是身份验证cookie过早过期(或者我猜是删除)。我们正在讨论来自数百家公司的数千名用户。许多人使用自己的PC而不是工作提供的PC。如果任何人有任何想法,我很乐意听到他们。

1 个答案:

答案 0 :(得分:0)

由于您使用的是Response.Add而不是SetCookie,因此您定义了一个固定的到期日期,这会使Cookie持久存在,如果用户有时会在两个小时内登录两次,那么

我会检查这是否不会混淆窗体auth模块。其中一个多个cookie可能会在某个时间点到期,滑动到期会迫使它重新发布。这可能会打开一个场景,其中单个请求中有多个cookie,其中一些可能已过期。

我的建议是使用http调试器来检查这个,然后替换代码,这可能会使你的auth cookie重复。