使用Tomcat允许子域会话cookie的最佳方法

默认情况下,tomcat将为当前域创建会话cookie。

如果您在www.example.com上,您的cookie将为www.example.com创建(仅适用于www.example.com)。 而对于example.com,它将为.example.com创建(期望的行为,将适用于example.com的任何子域以及example.com本身)。

我已经看到一些Tomcat阀门似乎拦截会话cookie的创建并使用正确的.example.com域创建替换cookie,但是它们似乎都没有完美地工作,它们似乎都离开了现有的cookie并且只是创造一个新的。 这意味着每个请求都会发送两个JSESSIONID cookie。

我想知道是否有人对此问题有明确的解决方案。

这显然是通过6.0.27及以后的配置设置支持的:

通过编辑META-INF / context.xml完成​​配置

https://issues.apache.org/bugzilla/show_bug.cgi?id=48379

我刚刚完成了所有这些寻找一个简单的解决方案。 我首先从tomcat的角度开始研究它。

Tomcat没有直接访问为会话配置域cookie,我绝对不想自定义补丁tomcat来修复该问题,如其他一些post所示。

由于访问Servlet规范中内置的头文件和cookie的限制,tomcat中的阀门似乎也是一个问题解决方案。 如果http响应在传递给您的阀门之前被提交,它们也会完全失败。

由于我们通过Apache代理我们的请求,因此我转而研究如何使用apache来解决问题。

我首先尝试了mod_proxy指令ProxyPassReverseCookieDomain,但它不适用于JSESSIONID cookie,因为tomcat没有设置域属性,并且如果没有某种域作为cookie的一部分,ProxyPassReverseCookieDomain就无法工作。

我还遇到了一个使用ProxyPassReverseCookiePath的黑客攻击,他们在那里重写了向cookie添加域属性的路径,但这让生产网站感到麻烦。

我终于通过使用apache中的mod_headers模块重写响应头来实现它,如上面Dave所述。

我在虚拟主机定义中添加了以下行:

Header edit Set-Cookie "(JSESSIONID\s?=[^;,]+?)((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(;\s?(?:(?i)Domain\s?=)[^;,]+?)?((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(,|$)" "$1$2; Domain=.example.com$4$5" 

以上应该都是配置中的单行。 它将使用“.example.com”替换任何JSESSIONID cookie域属性。 如果JSESSIONID cookie不包含域属性,则该模式将添加值为“.example.com”的cookie。 作为奖励,此解决方案不会受到阀门的双重JSESSION cookie问题的影响。

该模式应与Set-Cookie标头中的多个Cookie一起使用,而不会影响标头中的其他Cookie。 通过将模式的第一部分中的JSESSIONID更改为您想要的cookie名称,还可以修改其他cookie。

我不是高级用户,因此我确信可以对该模式进行一些优化,但到目前为止它似乎对我们有用。

如果我发现任何有关模式的错误,我会更新这篇文章。 希望这会阻止你们中的一些人像我一样经历过最后几天的挫折。

我在$ DAYJOB碰到了这个。 在我的情况下,我想实现SSL登录,然后重定向到非SSL页面。 tomcat的核心问题是SessionManager.configureSessionCookie方法(来自内存),该方法硬编码您想要访问的所有变量。

我提出了一些想法,包括在apache中使用mod_headers来基于正则表达式替换重写cookie的特别恶劣的黑客攻击。

解决这个问题的有效方法是向tomcat开发人员提交一个补丁,为SessionManager类添加可配置的参数。

由于会话(及其Id)基本上只被认为是发布应用程序的价值,您可能更愿意设置一个额外的cookie。 看看Tomcats SingleSignOnValve,为服务器路径“/”而不是“/ applicationName”提供额外的Cookie JSESSIONIDSSO(注意…… SSO)(因为通常设置JSESSIONID cookie)。

使用这样的Valve,您可以实现所需的任何进程间通信,以便在任意数量的tomcats / webservers / whatever上同步不同服务器,虚拟主机或webapp之间的任何状态。

您不能为自己的目的使用tomcats会话cookie的另一个原因是,同一主机上的多个webapps具有不同的会话ID。 例如,“/ webapp1”和“/ webapp2”有不同的cookie。 如果您将“/ webapp1”的cookie提供给“/ webapp2”,则无法找到您引用的会话,使会话+ cookie无效并设置自己的新会话。 您必须重写所有tomcats会话处理以接受外部会话ID值(安全方面的坏主意)或在应用程序之间共享某个状态。

会话处理应该被视为容器(tomcats)业务。 无论你需要什么,你应该添加而不干扰容器认为必须做的事情。

阀门技术似乎并非100%完美。 如果您敢于修改Tomcat本身:

catalina.jar包含以下类: org.apache.catalina.connector.Request

请求有一个方法:

 configureSessionCookie(Cookie cookie) 

对于我们的环境,最好只是硬编码,但你可以做更多奇特的逻辑:

 cookie.setDomain(".xyz.com"); 

似乎工作得很好。 如果可以在tomcat中配置,那将会很好。