我有一个侦听器可以动态设置会话超时
public class DynamicSessionTimeoutHttpSessionListener implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent event) {
long sessionTimeoutInMinute = ConfigEntryMgr.getInstance().getByKeyAsLong(ConfigEntryKeys.SESSION_TIMEOUT_IN_MINUTE);
event.getSession().setMaxInactiveInterval((int) sessionTimeoutInMinute * 60);
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
}
}
在Spring Security中,我不允许并发会话:
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry" />
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
</beans:bean>
<beans:bean
class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry" />
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
结果是没有人可以使用已经登录的用户名登录。
问题在于setMaxInactiveInterval不会破坏spring会话。
除非第一个用户再次打开浏览器并执行操作,否则servlet不会发现此会话已过期以触发SessionDestroyedEvent。
现在,如果第一个用户刚刚关闭浏览器,则没有人可以永远登录该用户,因为Spring Security认为仍然有人使用该用户名登录