我正在开发一种无状态REST API,该API利用基于 token 的身份验证,其中我是通过从自定义安全过滤器中调用SecurityContextHolder.getContext().setAuthentication(authentication)
手动将Authentication对象添加到安全上下文中的。我一直在遇到上下文设置不正确的问题,我认为这是由于以下原因:
Storing the SecurityContext between requests
In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use SecurityContextHolder.getContext(), and call setAuthentication(anAuthentication) on the returned context object, then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. ...
You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another.
因此,问题是-如何更改SecurityContextPersistenceFilter的行为?
我希望安全上下文不与http session 相关联,但不想将 session 创建策略设置为无状态,因为我仍然想实现CSRF保护等。
最佳答案
今天下午我有一个确切的问题,这个悬而未决的问题与我的搜索完全吻合,所以我想我会补充一点我学到的知识。
我们有访问相同SecurityContext的线程。我无法弄清楚如何直接自定义SecurityContextPersistenceFilter的行为(以及按照框架的模式),但是我可以通过两种方法使它成为线程安全的。
第一个解决方案是确保在我们的主身份验证过滤器中创建一个空上下文。这涵盖了我们所有经过身份验证的请求,因此适用于我们的解决方案。
SecurityContextHolder.createEmptyContext();
对我有用的第二件事是将我们的WebSecurityConfig更改为无状态,我知道这不适用于OP,但为了完整性起见在此添加了它。
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
...
这两种解决方案都针对我们的特定配置独立工作。我敢肯定有第三个解决方案会更好看,但是我不知道这是什么,但我想这么做。
这是我第一次发帖。我欢迎任何反馈。
关于multithreading - 如何自定义SecurityContextPersistenceFilter的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30781498/