我们有一个使用5年以上历史的Web应用程序,它使用Spring Security(3.1)功能对用户进行身份验证和授权。
基于访问代码APP2将信息显示给各个用户
下面是示例流程和Spring安全性重定向的示例格式:
重定向格式:
身份验证的代码流
@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);
}
以下是访问日志示例,供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的详细信息。
到目前为止我们几乎没有注意到:
下面是身份验证模块中使用的技术
我想知道问题是否在春季安全层(可能是注销处理程序)处,我们从HttpServletRequest对象获取重定向URL并将其传递给响应,但无法重现该问题。
任何输入或建议都会有所帮助。
答案 0 :(得分:0)
我们定义了自定义注销成功处理程序,如下所示
<sec:logout success-handler-ref="logoutSuccessHandler" invalidate-session="true" delete-cookies="JSESSIONID" />
我的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。