2016-06-18 3 views
2

Я хочу, чтобы запретить вход в систему, когда пользователь превысил максимальное количество сеансов. Например, каждый пользователь может войти в систему один раз. И затем, если зарегистрированный пользователь попробует другую систему входа в систему, он должен отключить логин для него.Весна Безопасность maxSession не работает

.sessionManagement() 
.maximumSessions(1).expiredUrl("/login?expire").maxSessionsPreventsLogin(true) 
.sessionRegistry(sessionRegistry()); 


@Bean 
public static ServletListenerRegistrationBean httpSessionEventPublisher() { 
    return new ServletListenerRegistrationBean(new HttpSessionEventPublisher()); 
} 

ответ

0

ПРИМЕЧАНИЕ: Это проверено на Spring MVC и 4.3.9.RELEASE, я не использовал Spring бутсу еще.

Я нашел решение, позвольте мне рассказать, как он работает со мной.

1) Я настроил HttpSecurity с SessionManagement следующим образом:

@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 
    ;   
} 

С помощью док Spring Doc > HttpSecurity > sessionManagement()

Пример конфигурации

следующая конфигурация демонстрирует, как обеспечить, что только Один экземпляр пользователя аутентифицируется одновременно. Если пользователь аутентифицируется с именем пользователя «пользователь» без выхода из системы и попытка аутентификации с «пользователем», первая сессия будет принудительно завершена и отправлена ​​на URL-адрес «/ login? Expired». @Configuration @EnableWebSecurity общественный класс SessionManagementSecurityConfig расширяет WebSecurityConfigurerAdapter {

@Override 
    protected void configure(HttpSecurity http) throws Exception { 
      http.authorizeRequests().anyRequest().hasRole("USER").and().formLogin() 
          .permitAll().and().sessionManagement().maximumSessions(1) 
          .expiredUrl("/login?expired"); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
      auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); 
    } } 

При использовании SessionManagementConfigurer.maximumSessions (INT), не забудьте Configure HttpSessionEventPublisher для приложения, чтобы истек сессии очищаются. В web.xml это может быть сконфигурирован , используя следующее:

<listener> 
     <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 

В качестве альтернативы, AbstractSecurityWebApplicationInitializer.enableHttpSessionEventPublisher() может вернуться верно.

Мы могли бы знать, почему мы должны sessionManagement(), maximumSessions(1), и конечно expiredUrl("/login?expired").

  • Так зачем нужна antMatchers("/login**").permitAll()? Так что вы могли бы иметь разрешение быть перенаправление на /login?expired, в противном случае вы будете перенаправлять /login потому что anyRequest().authenticated() с текущей конфигурацией HttpSecuritypermitAll() применяется к /login и /login?logout.

2) Если вам действительно нужно, чтобы получить доступ вошедшего в систему пользователя или expireNow() конкретной сессии для конкретного пользователя, как я, возможно, потребуется getSessionRegistry(), но без него maximumSessions(1) работает отлично.

Итак, еще раз с помощью док:

При использовании SessionManagementConfigurer.maximumSessions (INT), не забудьте Configure HttpSessionEventPublisher для приложения, чтобы истек сессии очищаются. В web.xml это может быть сконфигурирован , используя следующее:

<listener> 
     <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 

В качестве альтернативы, AbstractSecurityWebApplicationInitializer.enableHttpSessionEventPublisher() может вернуться верно.

Так что я должен изменить свое переопределение enableHttpSessionEventPublisher() в моем SecurityWebInitializer.java классе:

public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer { 
    @Override 
    protected boolean enableHttpSessionEventPublisher() { 
     return true; 
    } 
} 

3) Теперь только одна последняя вещь, которую я нашел это был мой вопрос: Как я новичок в Spring Framework , Я научился выполнять пользовательские UserDetails, но с небольшой неудачной реализацией, но я мог бы сделать лучше позже, я создал объект, который действует как как Entity, так и UserDetails:

@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

Смежные вопросы