5

最近我们遇到了一个严重的问题,一个用户得到了另一个用户的数据。这个问题几乎不可能重现。

我们正在使用 Spring-security 提供的标准登录用户管理,我们确信问题不在于将用户存储在实例变量中或在我们的应用程序中存储类似的并发内容。

我们真的怀疑问题出在 SpringSecurity 或 Tomcat 本身。

我们的前端服务器是 apache httpd,通过 ajp 连接器 (mod_jk) 连接到 tomcat。我们没有做任何负载平衡(httpd 只关心 SSL、一些 url 重写和服务一些 php 模块)

这是我们的设置:

## OS
OS Name:        Linux 
OS Version:     2.6.32-5-686
Architecture:   i386

## Apache httpd
Server version: Apache/2.2.16 (Debian)
Server built:   Sep  4 2011 20:27:42

## mod_jk
mod_jk/1.2.30 (installed via apt-get)

## JVM
JVM Version:    1.6.0_18-b18
JVM Vendor:     Sun Microsystems Inc.

## Tomcat
Server version: Apache Tomcat/6.0.28
Server built:   February 12 2011 1443

我们将此会话中的 httpd / mod_jk 混淆了,因此我们唯一的解决方案是删除 apache httpd。但在我们离开这个流行且广泛使用的配置之前,我们想知道是否有人遇到过类似的问题。

我发现的唯一类似问题是负载平衡或 mod_jk。

你有没有遇到过类似的问题?任何提示、想法、链接或经验都将受到高度赞赏。谢谢!

4

5 回答 5

1

如果您排除并发会话问题,那么几乎唯一的可能性是您的业务逻辑本身存在缺陷,并且为另一个用户的数据提供服务。请发布代码示例如何确定“当前用户”,并在以后使用。

编辑:仅在生产中表现出来的错误通常是由竞争条件(http://en.wikipedia.org/wiki/Race_condition)引起的。确保您的代码尽可能使用局部变量,并在适用的情况下使用锁定/同步。

于 2013-02-06T21:05:44.697 回答
1

可能的问题之一可能是第二次登录尝试。考虑以下情况:

  • 用户使用两个登录表单打开两个浏览器选项卡。
  • 选项卡 1:以 user_1 身份登录。将一些数据加载到 HTTP 会话中。
  • 选项卡 2:以 user_2 身份登录。将一些数据加载到 HTTP 会话中。

在大多数浏览器中,它将是相同的 HTTP 会话。因此,实际上您将来自 user_1 和 user_2 的数据组合在一个 HTTP 会话中。任何使用会话对象的页面都可能受到影响。

您在这里有两个选择:

  • 防止出现这种情况。检测第二次登录尝试并要求用户先注销。使用 Spring Security 很容易,请参见下面的代码。
  • 如果您绝对需要每个浏览器选项卡一个帐户,那么您可以将会话数据存储在每个用户名的映射中。

由于并发会话控制功能,您可以防止第二次登录尝试:

<http>
    ...
    <session-management>
        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
    </session-management>
</http>

它已经在您的应用程序中完成了吗?

于 2013-02-06T15:22:34.893 回答
1

到目前为止,我们无法重现该错误,但我们发现有些人在使用 mod_jk 时遇到了同样的问题:

所以现在我们正在使用以下设置运行:

我们计划将 mod_jk 切换为 mod_proxy_http。

我没有回答这个问题,因为我无法保证(并且没有人面临同样的问题能够保证)该解决方案修复了该错误。

如果有人可以分享任何信息,我将不胜感激!谢谢。

于 2013-02-19T09:33:07.417 回答
0

我在 Glassfish 3.1.2.2 和 Mod_JK 1.2.19 中遇到了同样的问题

您可以使用 JMeter 脚本和良好的断言来重现该错误。

这是我的博客文章讲述这个故事:http: //jeecookbook.blogspot.com/2013/07/modjk-session-mixed-between-users.html

使用带有此断言的 Mod_proxy 可以解决问题:不再检测到混合。

于 2013-07-04T05:12:33.803 回答
0

当您集成 JSF 和 Spring 时,JSF 依赖注入与 Spring 依赖注入发生冲突,因此 Spring 重写了处理该问题的 JSF 模块,以仅包装 Spring DI。因此,当我将 JSF ManagedBean 声明为 Session Scoped 时,我还必须给它一个@Controller注解,以便它也被识别为 Spring Bean。

有关更多信息,请参阅此。

于 2013-04-20T11:01:56.573 回答