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

时间:2016-07-06 08:38:00

标签: java session tomcat servlets jira

说明:

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

问题:

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

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

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

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

问题:

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

3 个答案:

答案 0 :(得分:1)

会话通常是"保持"通过使用会话cookie。如果客户在收到后没有提取该cookie,或者未将其包含在后续请求中,您将拥有您描述的方案。如果没有包含cookie,则没有确定的方法将第二个请求链接到第一个请求。

Jira会为这些请求创建会话听起来有点奇怪。如果它们确实是REST,它们将是无状态的并且不需要任何会话状态。我不知道关于Jira安装的事情,但我会先检查一下。

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

最后(这不是最终解决方案,但可以稍微缓解问题)您可以缩短特定Jira实例上的会话的生存时间。我再也不知道Jira设置,但通常认为这是可能的。如果此实例也为常规Web用户提供服务,请注意降低会话超时可能会对其产生负面影响(即需要更频繁地重新登录)。

答案 1 :(得分:1)

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

  

所以要在一般意义上解决这个问题,我们把它放在一起   atlassian-bot-killer插件。

     

这反过来通过颠倒这个想法。请求可能有   得到了一个会议,但它应该保留吗?

     

这个插件的作用是通过servlet过滤器监视每个请求   检查之前是否已经看过会话。如果不是,那一定是第一个   请求该会议。

     

然后将原始会话超时存储在会话本身和   将会话不活动超时设置为1分钟。如果是会话   发出第二个请求然后它被恢复到原始状态   超时说5个小时。如果你知道的话,它会升级   用户代理正在保留会话。

     

Web浏览器后面的用户经常会发出第二个请求毫秒   在第一次之后。 JavaScript,CSS文件都算作请求。那么一个   人类用户根本没有注意到这一点。

     

然而,Web bot不会保留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 :(得分:0)

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

如果非null,则可以获取用户名并将其与会话关联(ApplicationUser)。

如果外部工具只是访问标准的JIRA REST端点(即它不是你的代码),你需要使用{{Servlet Filter插件模块创建一个小的新JIRA插件。 1}},session.setAttribute(MY_USERNAME_KEY, applicationUser.getName())覆盖坏客户端正在访问的REST URL。你也应该能够注入location="before-dispatch",然后按照上面的步骤进行操作。

您如何选择枚举会话并检查最大值取决于您。一个选项,而不是直接将名称作为会话属性插入,而是将自定义对象作为实现<url-pattern>的会话属性插入,然后在JiraAuthenticationContext和{{1}中实现相应的回调}。我在JIRA中使用后一种方法用于其他会话管理目的,我可以确认回调是按预期调用的。