Spring的SecurityContextLogoutHandler
注意到clearAuthentication
标志用于:
从
Authentication
中删除SecurityContext
以防止并发请求出现问题。
从Authentication
移除SecurityContext
会阻止哪些具体问题?为什么不简单地使会话无效(这是SecurityContextLogoutHandler
的另一个责任)足够吗?
如果不清除SecurityContext
,SecurityContextPersistenceFilter
可能会将当前身份验证保留为新的会话ID吗?有效地让用户只使用新会话登录?
答案 0 :(得分:4)
clearAuthentication
标记
以前,当用户尝试访问时可能会出现竞争情况 一个缓慢的资源,然后注销,这将导致用户没有被记录 现在,来自。的SecurityContextLogoutHandler将从中删除身份验证 SecurityContext可以防止出现这种情况。
它在github上修复了这个issue(same issue)。引用:
如果SecurityContextPersistenceFilter执行需要大量时间,则如果会话从另一个线程失效,则HttpSessionSecurityContextRepository会恢复对会话的身份验证。
我正在使用Spring + JSF + DWR框架+ GWT事件服务(ajax push)。在任何时候,至少有一个线程在服务器端等待推送事件。此请求由SecurityContextPersistenceFilter处理,它记住请求到达服务器时的身份验证。如果在处理此过滤器期间会话无效(通过在管理区域中通过id忽略会话无效会话的另一个选项卡中的注销),则HttpSessionSecurityContextRepository将过时的身份验证放入新会话(由JSF框架创建,因此会话为在处理SecurityContextPersistenceFilter期间发生了变化。 如果将一些处理延迟插入SecurityContextPersistenceFilter,则可以轻松重现。
SaveToSessionResponseWrapper应该记住初始HttpSession并检查原始会话是否无效,因此它不会将当前身份验证设置为新会话。
答案 1 :(得分:4)
什么是SecurityContextLogoutHandler?
SecurityContextLogoutHandler是一个实现LogoutHandler的处理程序。
SecurityContextLogoutHandler的作用是什么?
SecurityContextHolder线程安全吗?
是的,使用默认策略(MODE_THREADLOCAL)是线程安全的(只要您不尝试动态更改策略)。但是,如果您希望生成的线程继承父线程的SecurityContext,则应设置MODE_INHERITABLETHREADLOCAL。
方面也没有任何“线程逻辑”,它们在与建议方法相同的线程上执行。
归功于@ axtavt
Spring Security中的身份验证是什么?
身份验证:框架尝试使用提供的凭据识别最终用户。可以对插入Spring Security的第三方系统进行身份验证。
让我们考虑一个每个人都熟悉的标准身份验证方案。
为用户建立安全上下文 用户继续执行某些可能受访问控制机制保护的操作,该访问控制机制根据当前安全上下文信息检查操作所需的权限。
前三项构成了身份验证过程,因此我们将了解这些内容是如何在Spring Security中进行的。
SecurityContextPersistentFilter
这个名字很明确。 SecurityContextPersistentFilter接口的目的是将安全上下文存储在某个存储库中。
要完成此任务,筛选器会将作业委派给SecurityContextRepository接口。
Spring为此接口提供了一个默认实现:org.springframework.security.web.context.HttpSessionSecurityContextRepository
。这是不言自明的。安全上下文的存储库只是当前的用户HTTP会话。
以下是SecurityContextPersistentFilter
<!-- Filter to store the Authentication object in the HTTP Session -->
<bean id="securityContextPersistentFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name="securityContextRepository" ref="securityContextRepository" />
</bean>
<bean id="securityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
LogoutFilter
LogoutFilter负责注销当前用户并使安全上下文无效。使HTTP会话无效的任务再次委托给另一个actor,即SecurityContextLogoutHandler。
此处理程序在LogoutFilter构造函数中注入:
<bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/pages/Security/logout.html" />
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/j_myApplication_logout"/>
</bean>
<constructor-arg value="/pages/Security/logout.html" />
- 它定义了注销页面的URL。
SecurityContextLogoutHandler在<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
注销操作的HTML网址由<property name="filterProcessesUrl" value="/j_myApplication_logout"/>
答案 2 :(得分:3)
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html 在请求之间存储SecurityContext
根据应用程序的类型,可能需要采用策略来在用户操作之间存储安全上下文。在典型的Web应用程序中,用户登录一次,然后通过其会话ID进行标识。服务器缓存持续时间会话的主体信息。在Spring Security中,在请求之间存储SecurityContext的责任属于SecurityContextPersistenceFilter,它默认将上下文存储为HTTP请求之间的HttpSession属性。它为每个请求恢复SecurityContextHolder的上下文,并且至关重要的是,在请求完成时清除SecurityContextHolder。 出于安全考虑,您不应直接与HttpSession进行交互。这样做完全没有理由 - 请始终使用SecurityContextHolder。
许多其他类型的应用程序(例如,无状态RESTful Web服务)不使用HTTP会话,并且会在每个请求上重新进行身份验证。但是,包含SecurityContextPersistenceFilter仍然很重要在链中确保在每次请求后清除SecurityContextHolder。
[注意]注意 在单个会话中接收并发请求的应用程序中,将在线程之间共享相同的SecurityContext实例。即使正在使用ThreadLocal,它也是从HttpSession为每个线程检索的相同实例。如果您希望临时更改运行线程的上下文,则会产生影响。如果您只使用SecurityContextHolder.getContext(),并对返回的上下文对象调用setAuthentication(anAuthentication),则Authentication对象将在共享同一SecurityContext实例的所有并发线程中更改。 您可以自定义SecurityContextPersistenceFilter的行为,为每个请求创建一个全新的SecurityContext,防止一个线程中的更改影响另一个。或者您可以在临时更改上下文的位置创建一个新实例。 SecurityContextHolder.createEmptyContext()方法总是返回一个新的上下文实例。
答案 3 :(得分:0)
SecurityContextLogoutHandler以标准的Servlet方式使Servlet会话无效,调用 对HttpSession对象的invalidate方法以及从Spring Security清除SecurityContext的方法。 SecurityContextLogoutHandler实现LogoutHandler接口 传统上,在Java Web应用程序中,用HttpSession对象管理用户会话信息。 在Spring Security(会话清算)中,在较低级别,情况仍然如此, Spring安全性引入了处理会话或用户会话信息的新方法。 在使用Spring Security的应用程序中,您很少直接访问Session对象以检索用户 细节。相反,您将使用SecurityContext(及其实现类)和SecurityContextHolder (及其实施类)。 SecurityContextHolder允许快速访问SecurityContext ,. SecurityContext允许快速访问Authentication对象,Authentication对象允许快速访问 访问用户详细信息。
例如,在编程之后说明了访问认证对象和显示消息
@Controller
@RequestMapping("/admin")
public class AdminController {
@RequestMapping(method = RequestMethod.POST, value = "/movies")
@ResponseBody
public String createMovie(@RequestBody String movie) {
System.out.println("Adding movie!! "+movie);
return "created";
}
@RequestMapping(method = RequestMethod.GET, value = "/movies")
@ResponseBody
public String createMovie() {
UserDetails user = (UserDetails)SecurityContextHolder.getContext().getAuthentication().
getPrincipal();
System.out.println("returned movie!");
return "User "+user.getUsername()+" is accessing movie x";
}
}
一旦完成身份验证,就会创建一个新会话; 创建会话后,它包含用户.on logout u need的信息 不仅要使会话无效,还需要清除会话信息
默认情况下 `isInvalidateHttpSession(`)
检查会话是否有效 如果会话有效
setInvalidateHttpSession(boolean invalidateHttpSession)
被调用。如何使会话对象无效,但会话对象仍包含信息。 清除需要调用的会话信息
setClearAuthentication(boolean clearAuthentication)
因此,如果不是第三种方法,方法就变得线程安全,它可以在低级别检索信息