java - 用户 session 困惑::Spring Security

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

我们有一个Web应用程序(已有5年以上的历史),它使用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的详细信息。两个用户都在同一时间(即小时,分钟,秒)访问身份验证应用程序。

我们已经定义了将始终使用默认目标属性设置为“ true”的定制表单登录,并且还在spring安全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的详细信息。

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


USER1,USER2在同一时间(即同一小时,分钟,秒)发送请求。从访问日志中,我们看到USER 2请求排在最前面,但是就响应而言,USER 1首先通过USER 2重定向URL获得了响应。
不会看到访问代码生成有很多问题,因为我们看到对于USER1,USER2来说,初始的Spring Security注销重定向似乎都有正确的细节
因此,我理解ELB除了X-Forwarded- *标头外,不会修改任何HTTP标头详细信息
USER1,USER2这两个请求均由同一EC2实例处理。经典ELB的默认行为是将每个请求独立地路由到负载最小的已注册实例。由于我们已经配置了粘性会话功能,因此负载均衡器可以将用户的会话绑定到特定实例。这样可以确保会话期间来自用户的所有请求都发送到同一实例
参考: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


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

任何意见或建议都会有所帮助。

最佳答案

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

<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。

关于java - 用户 session 困惑::Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55828899/

相关文章:

java - 一个项目中的两个 Spring MVC/Maven 模块

spring - Maven BOM用于解决Spring + Spring Data + Spring Security的依赖?

java - Spring登录表单从https切换为http

grails - SpringSecurity,如何记录由于启用==假而失败的尝试,grails 2.5

java - Path2D.intersect() 类似于 Area.intersect()

java - 在我的 "Custom Set"实现中需要帮助

java - 在 InputStream 中搜索

Java 到 C# Bitmap.createBitmap

java - spring mvc登录后重定向到主页

mysql - Hibernate 关于 join 的额外子句