我正在使用带有自定义提供程序和Mongo会话的Spring Oauth2。
当已经登录的用户导航到授权端点时,Spring为该用户创建一个新会话。我可以在mongoDB上看到该用户的多个重复会话。
有没有办法防止这种情况? 即,如果用户已经登录,请使用当前的Principal和会话,而不要创建新的Principal和会话。
配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors()
.and()
.authorizeRequests()
.antMatchers("/auth/**", "/oauth2/**", "/v1/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.authorizationEndpoint()
.baseUri("/oauth2/authorize")
.and()
.redirectionEndpoint()
.baseUri("/auth/callback/*");
}
答案 0 :(得分:1)
在这种情况下,您必须禁用或控制会话。
always – a session will always be created if one
doesn't already exist
ifRequired – a session will be created only if
required (default)
never – the framework will never create a
session itself but it will use one if it already
exists
stateless – no session will be created or used
by Spring Security
Java配置:
@Override
protected void configure(HttpSecurity http)
throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
当已通过身份验证的用户尝试再次进行身份验证时,应用程序可以通过以下几种方式之一处理该事件。它可以使用户的活动会话无效并通过新会话再次验证用户身份,或者允许两个会话同时存在。
启用并发会话控制支持的第一步是在web.xml中添加以下侦听器:
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
或将其定义为Bean –如下:
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
这对于确保在销毁会话时通知Spring Security会话注册表至关重要。
要启用允许同一用户进行多个并发会话的方案,应在XML配置中使用该元素:
<http ...>
<session-management>
<concurrency-control max-sessions="2" />
</session-management>
</http>
或者,通过Java配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().maximumSessions(2)
}
答案 1 :(得分:1)
经过研究,我发现这种行为是由于Spring的会话固定攻击保护所致。
默认情况下,Spring在重新认证时迁移会话,这使Spring通过复制上一个会话中的现有属性为用户创建一个新会话。
但是,发生这种情况时,spring-session-data-mongodb
不会出于某些原因删除旧的无效会话。我不确定spring-session-data-mongodb
为什么不删除旧的会话,所以如果有人对如何更改此设置有任何想法,请告诉我。
但是,如果要更改此行为,可以将会话固定设置更改为以下内容,以使spring在重新认证时使用现有的会话ID:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionFixation().none()
}