如何找到给定 HTTP 会话所属的用户

How to find the user to which a given HTTP session belongs

简介:

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

问题:

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

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

问题:

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

会话通常是 "kept" 通过使用 session cookie。如果客户端在收到时没有选择该 cookie,或者没有将其包含在后续请求中,那么您将遇到您描述的情况。如果不包含 cookie,则无法确定 link 第二个请求到第一个请求。

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

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

最后(这不是最终解决方案,但可以在一定程度上缓解问题)您可以缩短该特定 Jira 实例上 session 的 time-to-live。同样,我不知道 Jira 设置,但通常这应该是可能的。如果此实例还为普通网络用户提供服务,请注意降低 session 超时可能会对他们产生负面影响(即需要更频繁地 re-logon)。

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

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

如果外部工具只是访问标准的 JIRA REST 端点(即,这不是您的代码),您需要使用 location="before-dispatch"<url-pattern> 覆盖了不良客户端正在访问的 REST URL。您应该也可以在那里注入 JiraAuthenticationContext,然后只需按照与上述相同的步骤操作即可。

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

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

So to work around this problem in a general sense we put together the atlassian-bot-killer plugin.

This works on sessions by inverting the idea. A request may have gotten a session but does it deserve to keep it?

What this plugin does is watch every request via a servlet Filter and checks if it has seen the session before. If not it must be the first request for that session.

It then stores the original session timeout in the session itself and sets the session inactivity timeout to be 1 minute. If the session makes a second request then it gets bumped back to the original timeout of say 5 hours. It gets upgraded if you will since we know that the user agent is preserving sessions.

A user behind a web browser often makes a second request milliseconds after the first. JavaScript, CSS files all count as requests. So a human user does not notice this at all.

A web bot however does not preserve JSESSIONID cookies and hence is always presenting as a first request. These will then get a 1 minute time out and hence die quickly. The memory load on the server is greatly reduced.

REST requests from tools such as curl typically do no preserve sessions either and hence they can fall into the same class of request, even if they are done in terms of a user say via BASIC AUTH.

The atlassian-bot-killer follows the same strategy on requests with a known user however to be conservative it sets the inactivity time out to be 10 minutes instead of 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