2010-03-04 20 views
1

我遇到了ASP.NET MVC的一个问题,它迫使用户在大约20分钟的非活动状态后重新登录。在ASP.NET MVC会话中存储自定义委托人的问题

我使用窗体身份验证,并增加在配置文件中的超时为:

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

我也设置在配置文件中的会话超时为:

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

我立足这一关罗克福德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分钟后超时。我知道为什么发生这种情况,有什么想法?

我正在倾销表单身份验证并通过会话自己处理它的想法,但我恐怕会失去[授权]属性等功能。试着不要走这条路。

是否可以将自定义主体对象存储为cookie?我只是不希望为每一个页面或动作验证/授权用户。

我正在失去头发......迅速! =)

回答

2

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

您是否使用授权也隶属提供商见

+0

这是一个伟大的观点!所以只是因为我在Cookie中和会话状态中设置了超时设置......应用程序池可能会尽快回收它?那可能吗? – mattruma 2010-03-04 18:19:10

+0

无论如何要测试以查看哪些导致超时?我假设它是会议。 – mattruma 2010-03-04 18:20:06

+0

@mattruma,据我所知,App Pool可能会更快地回收它。但我不知道如何测试它。 IIS7具有应用程序池的回收设置。也许你应该试试这个。 – 2010-03-04 18:25:03

0

?如果是这样,您可能需要查看userIsOnlineTimeWindow属性。这个默认值也是20分钟。

+0

我正在使用成员资格提供程序,我自己的自定义实现......但仍在使用它。 – mattruma 2010-03-04 19:53:07

3

对于FormsAuthentication与SessionState的混合问题,在许多层面上只是一个坏主意,因为您从注意到的问题中注意到了这一点。

如果描述您的自定义委托人的信息很小,我建议将它存储在表格票证的UserData成员中。这就是它的目的。

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

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

Here是一个助手类,可以帮助您处理您的票。

CAVEAT:实际上,最大HTTP Cookie大小仅仅是官方4k限制的一小部分,加密会减少一半。

如果你能确保你的票据,包括主要数据将适合< 2k你应该是很好的去。为您的委托人创建自定义序列化可以提供帮助,例如如果您的数据合作,名称=值对的效果很好。

祝你好运。

+0

如果用户数据大小超过4k,您会推荐存储用户数据吗? – 2013-03-26 17:55:22

2

希望你得到这个解决了现在,但如果别人配备了同样的问题一直以来,我一直负责调试使用相同的模板写了一些代码,这里有几个想法:

1)表单票据有超时编码到它的值。大多数示例代码在那里对此超时进行硬编码,而不是从表单验证配置中拉出,因此如果您只是查看web.config,则一切看起来都不错,但您的自定义安全代码忽略了web.config的值。通过代码查看“新的FormsAuthenticationTicket”,看看你正在做什么过期时间。

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

3)某些客户端不会在响应重定向时设置cookie。有时即使他们这样做,你也会找回一个你设定的cookie以外的cookie。例如,如果您在任何时候更改了应用程序路径或域,则用户有可能拥有两个有效的Cookie,并且只有在您尝试将其重新登录到此处时才能清除一个。现在,这段代码基本上是这样写的:“用户有一些会话信息,并已登录,但是他们的会话没有包含我期望的主体,所以我重定向他们再次登录。”那么,如果他们不听你的授权cookie,或者有一个授权cookie,你不会期望(也许你在某个时候改变了你的域名或者路径值,他们仍然设置了/ oldpath cookie),这可能会导致无限循环。我建议一旦发现它没有你想要的数据,就会让会话服务器端发生变化:Session.Clear() - 这会让你在重定向之后不太可能最终出现这种情况。 (从服务器端的恢复 - 不信任客户端到行为的角度来看,实际上稍微安全些,重新构建主体对象并将其放入会话中,但我可以看到这将更少安全。)

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