我正在使用spring-security 3.1。
我必须以用户指定的最大会话数的方式实现会话并发策略。这是我做的:
编写一个扩展类 org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy并覆盖方法
protected int getMaximumSessionsForThisUser(Authentication authentication)
我使用命名空间配置配置它:
<security:http>
...
<security:session-management session-authentication-strategy-ref="mySessionAuthenticationStrategy"/>
...
</security:http>
<bean id="mySessionAuthenticationStrategy" class="foo.bar.MySessionAuthenticationStrategy">
<constructor-arg ref="sessionRegistry"/>
</bean>
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
问题是永远不会调用“MySessionAuthenticationStrategy”:(
我在spring api中挖掘了SessionManagementFilter
中的以下行(70)是错误的(阻止调用任何SessionAuthenticationStrategy
):
if (!securityContextRepository.containsContext(request))
为什么?
我阅读了他们建议在UsernamePasswordAuthenticationFilter
中设置会话身份验证策略的文档,但这对我来说不是一个选项,因为我将表单登录与SAML登录以及验证身份验证令牌的PreAuthentication
机制相结合( 3种不同的认证机制)。
你们中的任何人都可以提供帮助吗?
答案 0 :(得分:3)
简短回答(这是一个猜测):问题可能是您的预认证过滤器(或其他非形式登录过滤器)创建了一个会话而不首先调用SessionAuthenticationStrategy
。
冗长的解释:line you mentioned基本上是在没有auth-filter创建新会话的情况下检查请求是否刚刚在过滤器链的当前执行中进行了身份验证。检查检查是否存在会话,以及是否已将auth对象保存到会话中。
如果找到会话和保存的auth对象,则表示无需执行任何操作:在处理过程中,所有内容都已由其他过滤器或同一SessionManagementFilter
进行了身份验证和会话管理。先前在同一会话中提出的请求。
另一种情况是没有创建会话或者(非匿名)auth对象尚未保存在现有会话中。只有在这种情况下,SessionManagementFilter
才有责任通过调用SessionAuthenticationStrategy
来执行会话管理。
根据您的描述,第二种情况永远不会发生,这意味着会话已经创建,并且auth对象已经在此执行点保存。这应该意味着您的自定义身份验证过滤器必须创建一个会话,这本身不是问题。但是,一般规则是任何创建会话的人都必须先咨询SessionAuthenticationStrategy
本身。如果您的身份验证过滤器选择忽略它,则SessionManagementFilter
无法执行任何操作(即使SessionAuthenticationStrategy
已对用户的身份验证提出否决权,也无法撤消会话创建。)
如果是这种情况,请仔细检查,并尝试避免在预授权过滤器中创建会话。请注意,会话创建也可能在SaveToSessionResponseWrapper.saveContext()
被调用时以偷偷摸摸的方式发生,例如重定向。