ПРИМЕЧАНИЕ: Это проверено на 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()
с текущей конфигурацией HttpSecurity
permitAll()
применяется к /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