其他分享
首页 > 其他分享> > Spring Security maxSession不起作用

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