1

我遇到了 ASP.NET MVC 的问题,它强制用户在大约 20 分钟不活动后重新登录。

我正在使用表单身份验证并将配置文件中的超时时间增加为:

<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn" timeout="9999999" />
</authentication>

我还在配置文件中将会话超时设置为:

<sessionState timeout="120"></sessionState>

我基于 Rockford Lhotka 的 CSLA ASP.NET MVC 示例,并在我的 global.asax 中有以下内容:

    protected void Application_AcquireRequestState(object sender, EventArgs e)
    {
        if (HttpContext.Current.Handler is IRequiresSessionState)
        {
            if (Csla.ApplicationContext.AuthenticationType == "Windows")
                return;
            System.Security.Principal.IPrincipal principal;
            try
            {
                principal = (System.Security.Principal.IPrincipal)
                    HttpContext.Current.Session[MyMembershipProvider.SESSION_KEY];
            }
            catch
            {
                principal = null;
            }
            if (principal == null)
            {
                if (this.User.Identity.IsAuthenticated && this.User.Identity is FormsIdentity)
                {
                    // no principal in session, but ASP.NET token
                    // still valid - so sign out ASP.NET
                    FormsAuthentication.SignOut();
                    this.Response.Redirect(this.Request.Url.PathAndQuery);
                }
                // didn't get a principal from Session, so
                // set it to an unauthenticted PTPrincipal
                BusinessPrincipal.Logout();
            }
            else
            {
                // use the principal from Session
                Csla.ApplicationContext.User = principal;
            }
        }
    }

据我所知,它应该只在 120 分钟不活动后超时......但由于某种原因,它似乎总是在 20 分钟不活动后超时。我知道为什么会这样,有什么想法吗?

我正在玩弄只是转储表单身份验证并通过会话自己处理它的想法,但我担心我会失去像 [Authorize] 属性等功能。尽量不走这条路。

是否可以将我的自定义主体对象存储为 cookie?我只是不想为每个页面或操作对用户进行身份验证/授权。

我正在掉头发……很快!=)

4

4 回答 4

4

将 FormsAuthentication 的关注点与 SessionState 混合在许多层面上只是一个坏主意,正如您从得到的答案中注意到的那样。

如果描述您的自定义主体的信息很小,我建议将其存储在表单票证的 UserData 成员中。这就是它的用途。

然后,您的自定义数据(仅对有效票证有效)与票证一起存储。

解决了许多问题并消除了许多代码。

是一个帮助类,可以帮助你处理你的票。

警告:在实践中,最大 http cookie 大小略低于官方的 4k 限制,而 Encryption 将其减少了大约一半。

如果您可以确保您的票证(包括主要数据)适合 <2k,那么您应该很高兴。为您的主体创建自定义序列化会有所帮助,例如,如果您的数据能够合作,那么名称=值对会非常有用。

祝你好运。

于 2010-03-05T07:28:03.880 回答
2

通过 Session 处理它可能还不够。因为它可能是 IIS 回收您的应用程序,因此导致所有会话被放弃。

于 2010-03-04T17:40:10.067 回答
2

希望你现在已经解决了这个问题,但如果其他人遇到同样的问题,我一直负责调试使用相同模板编写的一些代码,这里有一些想法:

1) 表单票有一个超时编码到它的值中。大多数示例代码都对这个超时进行硬编码,而不是从表单身份验证配置中提取,所以如果您只是查看 web.config 一切看起来都很好,但您的自定义安全代码忽略了 web.config 值。查看“new FormsAuthenticationTicket”的代码,看看你在过期时间做什么。

2) 表单 cookie 在其 cookie 值中设置了超时。那里的一些示例代码对这个超时进行了硬编码。看看你是否在你的安全 cookie 上设置了 cookie.Expires。(自定义身份验证倾向于在此处手动构建比您预期的更多的代码,因为 FormsAuthentication 方法不公开 make-a-cookie-with-userdata 方法,并且您通常希望使用 userdata 来存储一些信息,例如角色在)

3) 一些客户端不会在响应重定向上设置 cookie。有时即使他们这样做了,你也会得到一个不同于你设置的饼干。例如,如果您在任何时候更改了应用程序路径或域,则用户可能拥有两个有效的 cookie,而您仅在尝试在此处重新登录时清除一个。现在,这段代码基本上是“用户有一些会话信息,并且已经登录,但他们的会话不包含我期望的主体,所以我将他们重定向到再次登录。” 好吧,如果他们不听您的 auth cookie,或者有一个您不期望的 auth cookie(也许您在某个时候更改了域或路径值并且他们仍然设置了 /oldpath cookie),这可以无限循环. 我建议您一发现会话服务器端没有 没有你想要的数据: Session.Clear() - 这让你在重定向后不太可能在这种情况下结束。(从recover-server-side-without-trusting-the-client-to-behave的角度来看,继续重建主体对象并将其放入会话中实际上稍微安全一些,但我可以看到这会更少安全的。)

只做一个 Server.Transfer 到登录页面也更安全,而不是依靠改变 cookie 的重定向来正常工作。如果您最终进入重定向循环,则 server.transfer 保证会结束它。

于 2010-09-06T06:19:11.530 回答
0

您是否也在使用会员提供商进行授权?如果是这样,您可能需要查看userIsOnlineTimeWindow属性。其默认值也是 20 分钟。

于 2010-03-04T19:20:55.560 回答