Spring Security maxSession不起作用
作者:互联网
当用户超过maxSession计数时,我想防止登录.例如,每个用户只能登录一次.然后,如果登录的用户尝试使用其他登录系统,则应禁用该用户的登录.
.sessionManagement()
.maximumSessions(1).expiredUrl("/login?expire").maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
解决方法:
注意:这已经在Spring MVC和4.3.9.RELEASE上进行了测试,我还没有使用过Spring Boot.
我找到了一个解决方案,让我分享它如何与我一起工作.
1)我使用SessionManagement配置了HttpSecurity,如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/login**").permitAll() // 1
.antMatchers(...)
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.sessionManagement() // 2
.maximumSessions(1) // 3
.maxSessionsPreventsLogin(false) // 4
.expiredUrl("/login?expired") // 5
.sessionRegistry(getSessionRegistry()) // 6
;
}
借助doc Spring Doc > HttpSecurity > sessionManagement()
Example Configuration
The following configuration demonstrates how to enforce that only a
single instance of a user is authenticated at a time. If a user
authenticates with the username “user” without logging out and an
attempt to authenticate with “user” is made the first session will be
forcibly terminated and sent to the “/login?expired” URL.06001
When using SessionManagementConfigurer.maximumSessions(int), do not forget to
configure HttpSessionEventPublisher for the application to ensure that
expired sessions are cleaned up. In a web.xml this can be configured
using the following:06002
Alternatively,
AbstractSecurityWebApplicationInitializer.enableHttpSessionEventPublisher()
could return true.
我们可以知道为什么需要sessionManagement(),maximumSessions(1),当然还需要expiredUrl(“ / login?expired”).
>那么为什么需要antMatchers(“ / login **”).permitAll()?
这样您便可以重定向到/ login?过期,否则,您将被重定向到/ login,因为将具有当前HttpSecurity配置的allowRequest().authenticated()和当前/ etc / login?logout应用于的HttpSecurity配置.
2)如果您实际上需要访问像我这样的特定用户的当前登录用户或expireNow()特定会话,则可能需要getSessionRegistry(),但没有它,maximumSessions(1)可以正常工作.
因此,再次在文档的帮助下:
When using SessionManagementConfigurer.maximumSessions(int), do not forget to
configure HttpSessionEventPublisher for the application to ensure that
expired sessions are cleaned up. In a web.xml this can be configured
using the following:06002
Alternatively,
AbstractSecurityWebApplicationInitializer.enableHttpSessionEventPublisher()
could return true.
因此,我应该在SecurityWebInitializer.java类中更改覆盖的enableHttpSessionEventPublisher():
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected boolean enableHttpSessionEventPublisher() {
return true;
}
}
3)现在我发现的最后一件事是我的问题:
当我刚接触Spring框架时,我学会了自定义UserDetails,但是实现起来有些不好,但是以后可能会做得更好,我创建了一个同时充当Entity和UserDetails的Entity:
@Entity
@Component("user")
public class User implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
// ...
@Override
public boolean equals(Object obj) {
if (obj instanceof User) {
return username.equals( ((User) obj).getUsername() );
}
return false;
}
@Override
public int hashCode() {
return username != null ? username.hashCode() : 0;
}
}
我在几年前的论坛here中找到了一个推荐的建议,您应该实现两个hashCode()equals()方法,如果您查看UserDetails User.java
的默认实现的源代码,您会发现它已经实现了这两种方法,我做到了,它就像一种魅力.
就是这样,希望对您有所帮助.
您可能也要阅读此链接:Spring – Expiring all Sessions of a User
标签:spring-security,spring-session,spring 来源: https://codeday.me/bug/20191118/2028755.html