【问题标题】:How to find the user to which a given HTTP session belongs如何找到给定 HTTP 会话所属的用户
【发布时间】:2016-11-08 05:53:39
【问题描述】:

简介:

我有一个 JIRA 实例,许多外部工具通过 REST 使用该实例。其中一些工具不会重复使用它们创建的 HTTP 会话,这会导致为每个请求创建一个新会话。

问题:

创建过多会话会导致不可接受的资源消耗。所以我正在寻找一种方法:

  • 通过拒绝他们的登录尝试来限制行为不端的客户不要创建太多会话 - 从而迫使他们的所有者修复他们的客户

  • 使旧会话无效,从而释放服务器上的资源

但为了做到这一点我需要知道给定会话属于哪个用户,所以当用户 X 达到让我们说 5 个会话的限制时 - 我可以使他的旧会话无效或拒绝他的请求。

问题:

如何将会话映射到来自 HttpSessionListener 的用户? 有没有更好的方法来实现我的目标?也许是 JIRA 特定的东西?

【问题讨论】:

    标签: java session tomcat servlets jira


    【解决方案1】:

    我找到了一个非常聪明的方法来实现我的目标:

    为了解决这个问题,我们将 atlassian-bot-killer 插件。

    这通过颠倒想法在会话上起作用。一个请求可能有 得到了一个会话,但它值得保留吗?

    这个插件的作用是通过一个 servlet 过滤器和 检查它之前是否看过会话。如果不是,它必须是第一个 请求该会话。

    然后它将原始会话超时存储在会话本身中,并 将会话不活动超时设置为 1 分钟。如果会话 发出第二个请求,然后它被撞回原来的 超时说5小时。如果您愿意,它会升级,因为我们知道 用户代理正在保留会话。

    Web 浏览器后面的用户通常会在几毫秒内发出第二个请求 在第一个之后。 JavaScript、CSS 文件都算作请求。所以一个 人类用户根本不会注意到这一点。

    但是,网络机器人不保留 JSESSIONID cookie,因此是 总是作为第一个请求出现。然后这些将获得 1 分钟 超时,因此很快死去。服务器上的内存负载是 大大减少了。

    来自 curl 等工具的 REST 请求通常不会保留 会话,因此它们可以属于同一类 请求,即使它们是根据用户通过 BASIC AUTH 完成的。

    atlassian-bot-killer 对带有 已知用户,但是为了保守起见,它设置了不活动超时 是 10 分钟而不是 1 分钟。

    来源:http://blogs.atlassian.com/2012/03/getting-rid-of-unwanted-http-sessions/

    PS:其实有一个现成的插件:https://marketplace.atlassian.com/plugins/com.atlassian.labs.atlassian-bot-killer/versions

    【讨论】:

      【解决方案2】:

      会话通常通过使用会话 cookie 来“保留”。如果客户端在收到该 cookie 时没有获取该 cookie,或者没有将其包含在后续请求中,那么您将遇到您描述的场景。如果不包含 cookie,则无法确定将第二个请求链接到第一个请求的方法。

      Jira 会为这些请求创建会话,这听起来有点奇怪。如果它们真的是 REST,它们将是无状态的并且不需要任何会话状态。虽然我对 Jira 安装一无所知,但我会先检查一下。

      无论如何,我可以想到一些方法来缩小“不良”客户的范围。一种是检查导致新会话的传入请求中的“User-Agent”标头。您可能会发现用户代理会导致更多新会话的模式,而用户代理不会。它可能是也可能不是一个选项,但您可以暂时“禁止”这些用户代理并等待他们向您抱怨;-) 其他方法是通过请求 IP 地址,这可以让您追溯到罪魁祸首并解释问题。

      最后(这不是最终解决方案,但可以在一定程度上缓解问题)您可以缩短该特定 Jira 实例上会话的生存时间。同样,我不知道 Jira 设置,但通常这应该是可能的。如果此实例也服务于普通 Web 用户,请注意降低会话超时可能会对他们产生负面影响(即需要更频繁地重新登录)。

      【讨论】:

      • 感谢您的回答! REST api 是 BASIC auth 保护的,并且经过身份验证的调用会导致创建新会话,除非其余客户端发送会话 cookie,而坏客户端不会这样做。他们使用一些不处理会话的基于 java 的 rest-api 包装器(jira rest 客户端)。 you could shorten the time-to-live - 这不是一个真正的选择,因为其中一个客户在几分钟内创建了大约 2k 个会话 :) 所以我必须将会话超时减少到一个低得离谱的值
      【解决方案3】:

      假设这些工具正在调用您自己创建的 REST 插件点:在这些方法的上下文中,您可以将 JiraAuthenticationContext 注入您的 bean 并调用 getLoggedInUser() 以获取当前的 ApplicationUser 对象用户。

      如果非空,您可以获取用户名并将其与会话关联 (session.setAttribute(MY_USERNAME_KEY, applicationUser.getName()))。

      如果外部工具只是访问标准 JIRA REST 端点(即它不是您的代码),则您需要使用location="before-dispatch" 创建一个带有Servlet Filter 插件模块的小型新JIRA 插件,并带有@987654327 @ 覆盖坏客户端正在访问的 REST URL。您应该也可以在那里注入JiraAuthenticationContext,然后按照与上述相同的步骤进行操作。

      如何选择枚举会话并检查最大值取决于您。一种选择不是直接插入名称作为会话属性,而是插入自定义对象作为实现HttpSessionBindingListener 的会话属性,然后在valueBoundvalueUnbound 中实现适当的回调。我在 JIRA 中将后一种方法用于其他会话管理目的,我可以确认回调是按预期调用的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2015-06-08
        • 2015-05-05
        • 2018-02-12
        • 1970-01-01
        • 1970-01-01
        • 2012-05-07
        相关资源
        最近更新 更多