spring-security - SP 超时时 SLO 失败
问题描述
使用 Spring Security SAML 1.0.10,当 SAML 会话在 SP 上超时,但在 IdP 上仍处于活动状态时,SLO 尝试将失败。
如何重现
- 将会话超时设置为一分钟(server.servlet.session = 1m)
- 登录您的 SP
- 在不同的辅助 SP 上登录 - 它必须使用 SSO
- 等待一分钟会话超时
- 在辅助 SP 上进行锁定
这会在 Spring 中导致 ClassCastException,因为SecurityContextHolder.getContext().getAuthentication()
包含AnonymousAuthenticationToken
不包含凭据的。它还破坏了过滤器链,并且永远不会向 IdP 发送 LogoutResponse,并且浏览器中会显示错误页面。
java.lang.ClassCastException: class java.lang.String cannot be cast to class org.springframework.security.saml.SAMLCredential (java.lang.String is in module java.base of loader 'bootstrap'; org.springframework.security.saml.SAMLCredential is in unnamed module of loader 'app')
at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:172)
这是有意的,是错误还是我配置错误?如果它是有意的或错误的,是否存在解决方法?
解决方案
错误发生在SAMLLogoutProcessingFilter.processLogout()
以下代码导致 ClassCastException 的位置。如果用户会话超时,则auth.getCredentials()
返回空字符串。
SAMLCredential credential = null;
if (auth != null) {
credential = (SAMLCredential)auth.getCredentials();
}
我发现的唯一解决方法是创建一个处理该问题的 LogoutFilter。
我创建了一个扩展 SAMLLogoutProcessingFilter 的新 LogoutFilter。在 LogoutRequest 和 AnonymousAuthenticationToken 的情况下,我创建了一个 LogoutResponse。在任何其他情况下,我转发到 SAMLLogoutProcessingFilter 或从 SAMLLogoutProcessingFilter 调用方法的副本,其中我删除了失败的部分。
private void overwrittenLogout(HttpServletRequest request, HttpServletResponse response, SAMLMessageContext context)
throws ServletException, SAMLException, MetadataProviderException, MessageEncodingException
{
var auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof AnonymousAuthenticationToken) {
logoutProfile.sendLogoutResponse(context, StatusCode.SUCCESS_URI, null);
} else if (auth != null) {
followNormalProcedure(request, response, auth, context);
}
}
推荐阅读
- r - 使用 ggpairs 获取相关值
- replaceall - 如何用下划线替换数据框中的所有空格?
- docker - Dockerized elasticsearch and fscrawler:未能创建elasticsearch客户端,禁用爬虫......连接被拒绝
- php - 在 PHP 中从 cURL 请求解析 XML
- windows - Firebird DB 日志文件位于 Windows 中的什么位置?
- java - 一个执行器中有多少并发任务,Spark 如何处理一个执行器中的任务之间的多线程?
- typescript - 打字稿:无效联合类型
- laravel - 使用存储在 redis 中的模型中的水合物来保留雄辩的关系
- momentjs - 如何根据行程预订时间查找 24 小时差异
- flutter - 如何自动更新文本小部件 - Flutter