我最近实现了
SwitchUserFilter
在我的Spring(4.3.17)应用程序中。虽然最初看起来一切正常,但我们开始遇到403
Access Denied
错误,或者在退出模拟后突然被重定向到我们的登录页面,然后尝试重新模拟同一个或另一个用户。
我花了整整三天的时间在这方面,并在这一点上深入到Spring的深处进行了调试,主要集中在过滤器链和身份验证上,试图了解发生了什么。我发现我们遇到了以下情况:
-
管理员用户模拟标准用户
-
管理员用户退出模拟
在页面完全加载之前
(AJAX请求待定)
-
管理员已正确重定向到
SwitchUserFilter
出口
targetUrl
...此时,Spring security/auth/角色在过滤器链、会话和应用程序中看起来都是正确的
SecurityContext.contextHolder
然后
-
Spring开始处理源自上述步骤2的Ajax请求。
-
Spring为来自会话的延迟请求加载身份验证,并且
模拟用户的身份验证
.
-
Spring处理请求,进行身份验证,因为它将当前会话视为用户的会话,并且过滤器链更新
SecurityContext
和
模拟会话
.
此时,管理员用户正坐在一个只有管理员的页面上,但幕后Spring已经覆盖了
SecurityContext
使用用户的身份验证。现在,如果管理员试图重新加载页面,他们将重定向到管理员登录。如果他们试图模仿,他们会看到一个通用的403。
在我看来,执行步骤5的唯一方法是,如果Spring从会话中加载了用户身份验证,然后用户退出模拟,Spring将管理员的身份验证恢复到会话中,最后Spring完成了(过时的)用户会话身份验证的处理,并最终用用户的身份验证覆盖管理员会话身份验证。
抱歉,这太冗长了,这几天令人沮丧,我不知道该怎么办。在我看来,这可能与线程有关,所以我想问一下,当然,提供必要的上下文。