用户会话混乱:: Spring Security

时间:2019-04-24 11:22:40

标签: java spring-mvc spring-security amazon-elb

我们有一个使用5年以上历史的Web应用程序,它使用Spring Security(3.1)功能对用户进行身份验证和授权。

  • 作为身份验证过程的一部分,我们创建一个随机的20个字符的访问代码(ac)和5个字符的用户编号(un)
  • 验证成功后,我们将重定向到另一个应用程序,该应用程序将访问码,用户号作为查询参数传递给
  • 基于访问代码APP2将信息显示给各个用户

    下面是示例流程和Spring安全性重定向的示例格式:

enter image description here

重定向格式:

https://APP1_HOST:PORT/auth/j_spring_security_logout?redirectUrl=https://APP2_HOST/abc/AccessServlet?ac=astqcssq-Z-3R2LOFjy-&un=12345

身份验证的代码流

@RequestMapping(value="/Authentication.do")
public String doWAuthentication(ModelMap model) {

    User user = super.getUser();        

    String url = app2Baseroot; // instance variable - APP2 Host name

    //generate parameters - static methods
    String accessCode = Utils.generateString(20);
    String userNo = Utils.generateUserNumber(5);

    //write authentication details for APP2 to retrieve
    userDao.saveAuthenticationDetails(user, accessCode, userNo);

    //Add redirection specifics - servlet name & query params
    try {
        url += java.net.URLEncoder.encode("AccessServlet?ac="+accessCode+"&un="+userNo, "UTF-8");
    } catch (UnsupportedEncodingException uee) {

        LOG.error("Unable to encode redirect URL: "+uee.toString());
    }

    //redirect via spring security logout
   // AuthBaseroot - Instance variable - APP1 host name
    return "redirect:"+AuthBaseroot+"j_spring_security_logout?redirectUrl="+url;
}

我们最近遇到了一个问题,由于重定向URL混杂在一起,USER 1能够查看USER 2的详细信息。两个用户都同时(即小时,分钟,秒)访问身份验证应用程序。

我们定义了自定义表单登录,其 always-use-default-target 属性设置为“ true ”,并且还在spring security XML中配置了自定义注销处理程序文件:

<sec:logout success-handler-ref="logoutSuccessHandler" invalidate-session="true" delete-cookies="JSESSIONID" />

LogoutSuccessHandler扩展SimpleUrlLogoutSuccessHandler并覆盖onLogoutSuccess。该方法所做的就是从HttpServletRequest获取重定向URL,并将其设置为

AbstractAuthenticationTargetUrlRequestHandler。 setDefaultTargetUrl(URL)并调用super方法(super.onLogoutSuccess)。

public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException, ServletException {

    //Set redirection to APP2 url containing security params
    super.setDefaultTargetUrl(request.getParameter("redirectUrl"));

    super.onLogoutSuccess(request, response, authentication);
}
  • 我们的应用程序托管在 AWS 中,并使用经典的ELB,并且作为安全性的一部分,所有请求都通过封装imperva进行流
  • ELB启用了“ 应用程序生成的cookie粘性
  • 的粘性
  • 我们还在ELB层启用了访问日志,并检查了访问日志,我们可以看到USER1,USER2的重定向URL混在一起了

以下是访问日志示例,供USER1,USER 2用作参考

用户2:

2019-04-20T09:34:11.328056Z XXX.XXX.XX.XX:XXXXX XX.XXX.XXX.XXX:80 0.000171 0.050725 0.0001 302 302 0 321 
"GET https://APP1_HOST:PORT/auth/j_spring_security_logout?redirectUrl=https://APP2_HOST/link/AccessServlet%3Fac%3DWA-FF7WlNowjyu2R-XaU%26un%3D12345 
HTTP/1.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2

2019-04-20T09:34:11.413849Z XXX.XXX.XX.XX:XXXXX XX.XXX.XXX.XXX:80 0.000074 0.003343 0.000073 200 200 0 799 
"GET https://APP2_HOST/link/AccessServlet%3Fac%3DWA-FF7WlNowjyu2R-XaU%26un%3D12345
HTTP/1.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2

USER 2访问日志证明Spring安全性注销j_spring_security_logout中的重定向URL与实际重定向匹配。

用户1

2019-03-26T09:34:11.349198Z XXX.XXX.XX.XX:XXXXX XX.XXX.XXX.XXX:80 0.000137 0.030374 0.00011 302 302 0 321
"GET https://APP1_HOST:PORT/auth/j_spring_security_logout?redirectUrl=https://APP2_HOST/link/AccessServlet%3Fac%3Dn--qcvnq-Z-3R2LOFjy-%26un%3D13267 
HTTP/1.1" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/73.0.3683.86 Safari/537.36" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2

2019-03-26T09:34:11.408386Z XXX.XXX.XX.XX:XXXXX XX.XXX.XXX.XXX:80 0.000066 0.007958 0.000077 200 200 0 1365 
"GET https://APP2_HOST/link/AccessServlet%3Fac%3DWA-FF7WlNowjyu2R-XaU%26un%3D12345 
HTTP/1.1" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/73.0.3683.86 Safari/537.36" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2

第一条语句显示了USER 1带有正确重定向URL的j_spring_security_logout,但是随后对重定向URL的调用似乎已经与USER 2混淆了。由于用户详细信息基于访问代码USER 1进行,能够查看USER 2的详细信息。

到目前为止我们几乎没有注意到:

  1. USER1,USER2在同一时间(即同一小时,分钟,秒)发送请求。从访问日志中,我们看到USER 2请求排在最前面,但是就响应而言,USER 1首先通过USER 2重定向URL获得了响应。
  2. 访问代码生成没有太大问题,因为我们看到USER1,USER2的初始Spring安全性注销重定向似乎都具有正确的细节
  3. 我理解,这样的ELB除了X-Forwarded- *标头外,不会修改任何HTTP标头详细信息
  4. USER1和USER2的请求均由同一EC2实例处理。经典ELB的默认行为是将每个请求独立地路由到负载最小的已注册实例。由于我们已配置为粘性会话功能,因此该功能使负载均衡器可以将用户的会话绑定到特定实例。这样可以确保会话期间来自用户的所有请求都发送到同一实例 REF:https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-sticky-sessions.html

下面是身份验证模块中使用的技术

  • Java – 1.6
  • Spring MVC,Spring Security(版本3.1)
  • Servlet API – 2.4
  • OC4J服务器(10.1.3.5)
  • 部署在AWS中–使用传统的ELB

我想知道问题是否在春季安全层(可能是注销处理程序)处,我们从HttpServletRequest对象获取重定向URL并将其传递给响应,但无法重现该问题。

任何输入或建议都会有所帮助。

1 个答案:

答案 0 :(得分:0)

我们定义了自定义注销成功处理程序,如下所示

<sec:logout success-handler-ref="logoutSuccessHandler" invalidate-session="true" delete-cookies="JSESSIONID" />
  • logoutSuccessHandler类扩展了SimpleUrlLogoutSuccessHandler类,而该类又扩展了AbstractAuthenticationTargetUrlRequestHandler。
  • SimpleUrlLogoutSuccessHandler和AbstractAuthenticationTargetUrlRequestHandler是Spring类的一部分
  • 在我的情况下,logoutSuccessHandler是单例,父类也是单例
  • 我的logoutSuccessHandler中的onLogoutSuccess重写方法从请求中更新DefaultTargetUrl值并调用super.handle方法

    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException, ServletException {
    
    super.setDefaultTargetUrl(request.getParameter("redirectUrl"));
    
    super.onLogoutSuccess(request, response, authentication);
    

    }

DefaultTargetUrl 是AbstractAuthenticationTargetUrlRequestHandler.class的实例变量。

在我的问题场景中,两个用户(USER1,USER2)均在同一实例中处理/处理,并且请求同时接收。由于自定义处理程序,spring组件是单例的,并且上述两个步骤不是原子的,因此线程(t01)可能会覆盖另一个线程(t02)设置的DefaultTargetUrl。