【问题标题】:Spring security fail in load balanced (AWS Beanstalk) environment?负载平衡(AWS Beanstalk)环境中的 Spring 安全性失败?
【发布时间】:2014-09-29 11:47:56
【问题描述】:

我正在处理在现有环境中运行良好的现有代码。该应用程序有一个登录表单,可在用户登录后将其带到登录页面。

我的问题:当我将应用程序移动到 AWS Beanstalk(有 2 个实例)时,成功登录会将用户带回登录页面

该应用程序是基于 Spring 的(MVC,安全性),具有以下安全配置:

<security:http use-expressions="true">
    <security:intercept-url pattern="/" access="permitAll" />
    <security:intercept-url pattern="/index.html" access="permitAll" />
    <security:intercept-url pattern="/login.html" access="permitAll" />

    ... bunch of other pages ....

    <security:intercept-url pattern="/secure/**" access="isAuthenticated()" />


    <security:form-login login-page="/login.html"
        default-target-url="/secure/landing.html"
        authentication-failure-url="/login.html?login_error=1" />

    <security:logout logout-url="/logout.html"
        logout-success-url="/login.html" />
</security:http>

应用程序在单节点环境中运行良好,例如用户登录时的日志跟踪:

1: [http-bio-8080-exec-1 DEBUG DefaultRedirectStrategy - sendRedirect - 重定向到'/myapp/secure/landing.html'

2: [http-bio-8080-exec-1] DEBUG HttpSessionSecurityContextRepository - saveContext - SecurityContext 存储到 HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@86073c69: /*一些细节 */ 授予权限:ROLE_USER'

3: [http-bio-8080-exec-1] DEBUG SecurityContextPersistenceFilter - doFilter - SecurityContextHolder 现在已清除,因为请求处理已完成

4: [http-bio-8080-exec-1] DEBUG AntPathRequestMatcher - 匹配 - 检查请求的匹配:'/secure/landing.html';反对'/resources/**'

当这个应用程序(我们使用完全相同的 war 文件)进入 AWS Beanstalk 环境并配置了 2 个实例时,会发生以下情况:

1: [http-bio-8080-exec-7] DEBUG DefaultRedirectStrategy - sendRedirect - 重定向到'/secure/landing.html'

2: [http-bio-8080-exec-7] DEBUG HttpSessionSecurityContextRepository - createNewSessionIfAllowed - HttpSession 被创建为 SecurityContext 是非默认的

3: [http-bio-8080-exec-7] DEBUG HttpSessionSecurityContextRepository - saveContext - SecurityContext 存储到 HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@a3421210: /* 一些细节 */ Granted Authorities: ROLE_USER'

4: [http-bio-8080-exec-7] 调试 SecurityContextPersistenceFilter - doFilter - SecurityContextHolder 现在已清除,因为请求处理已完成

5: [http-bio-8080-exec-9] 调试 AntPathRequestMatcher - 匹配 - 检查请求的匹配:'/login.html';反对'/resources/**'

逐行比较:

  • AWS 日志多了 1 行,第 2 行
  • AWS 日志在最后一行第 5 行显示线程从 exec-7 更改为 exec-9(因此它丢失了原始请求重定向并将其替换回 /login.html 而不是 /secure/landing.html )

为了解决 AWS 中出现的问题,将 beanstalk 重新配置为仅适用于 1 个实例似乎可以隐藏问题。

知道在多节点环境中失败的配置缺少什么吗?

【问题讨论】:

  • 你用什么来做实例之间的负载均衡?弹性负载均衡器?
  • 使用 beanstalk(设置为“负载平衡,自动缩放”),所以是的,我认为它自动带有弹性负载平衡器?在 beanstalk 配置中,我通过将“最小实例数”设置为 1 来解决该问题,当它设置为 2 时遇到问题
  • 在您的 Elastic Load Balancer 配置中,您是否对应用程序生成的 cookie 使用粘性会话?特别是您是否将负载均衡器设置为使用 JSESSIONID 作为 cookie 以用于应用程序粘性会话?见这里:docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/…
  • @RobBlake:与您发送的链接略有不同,因为这是通过 Beanstalk,但是是的,似乎配置“粘性会话”修复它。谢谢!

标签: java spring amazon-web-services spring-security amazon-elastic-beanstalk


【解决方案1】:

在使用负载均衡器时,您必须记住,每个请求都可以在不同的实例上结束。在这种情况下,服务器 1 上存储的任何信息都对服务器 2 不可用。在用户身份验证的情况下,有几种方法可以解决此问题:

  • 使用第三方维护身份验证信息。
  • 使用粘性会话 - 将负载平衡器配置为始终转发到一台服务器 在 http 会话期间

【讨论】:

  • 是的,但奇怪的是这发生在一个请求中。如果您看到 AWS 日志文件,它只是在单个请求中更改线程(当时除了我自己之外没有人在使用系统)。一旦一个请求通过负载均衡器并进入一个实例,它不应该在那里(并且在同一个线程中)直到它完成吗?
  • 第二部分的日志是否来自一个实例?你认为这两行是来自两个不同的实例吗?
  • 一旦重定向在登录后被发送到浏览器,它就是一个新的请求和潜在的新线程。您是否检查了第二台服务器上的日志,您是否看到了landing.html 的请求。可能发生的情况是用户在服务器 1 上登录,重定向到登陆,然后命中服务器 2。服务器 2 重定向到登录(因为它不知道用户已通过身份验证)并且该请求命中服务器 1
【解决方案2】:

根据Spring Security documentation,您需要确保您的 SecurityContextHolder bean 是使用非 ThreadLocal 模式设置的。默认情况下,我相信它是使用 MODE_THREADLOCAL 设置的,它似乎不会在弹性 beanstalk 设置的线程系统中持续存在。

strategyName = SecurityContextHolder.MODE_INHERITABLETHREADLOCALMODE_GLOBAL 注入您的SecurityContextHolder bean,如果可行,请告诉我。

【讨论】:

    猜你喜欢
    • 2015-08-02
    • 2019-12-22
    • 2020-10-25
    • 2015-09-27
    • 2019-11-03
    • 2017-09-21
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多