Spring security - expiredUrl не работает
Мне нужно настроить expired-url
в моем приложении Spring MVC. Вот мои усилия, но не имеет никакого эффекта:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(adminAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(customerAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf()
.disable()
.authorizeRequests()
.antMatchers("...", "...", "...").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login")
.and()
.logout()
.addLogoutHandler(customLogoutHandler())
.logoutSuccessHandler(customLogoutSuccessHandler())
.logoutUrl("/logout")
.deleteCookies("remove")
.invalidateHttpSession(true)
.permitAll()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired");
}
Это не имеет никакого эффекта, и когда сеанс пользователя заканчивается, Spring не перенаправляет его на URL /expired
и просто перенаправляет его на /admin/login
url.
Update:
Я пробовал предлагаемые решения в комментариях и ответах, но не видел никакого эффекта. Также я удалил addLogoutHandler()
, logoutSuccessHandler()
и два addFilterBefore()
в начале метода, но не работал.
Также я попробовал другое решение таким образом:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(sessionManagementFilter(), SessionManagementFilter.class)
.csrf()
.disable()
.authorizeRequests()
.antMatchers("...", "...", "...").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login")
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("remove")
.invalidateHttpSession(true)
.permitAll();
}
@Bean
public SessionManagementFilter sessionManagementFilter() {
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(httpSessionSecurityContextRepository());
sessionManagementFilter.setInvalidSessionStrategy(simpleRedirectInvalidSessionStrategy());
return sessionManagementFilter;
}
@Bean
public SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy() {
SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy("/expired");
return simpleRedirectInvalidSessionStrategy;
}
@Bean
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository(){
HttpSessionSecurityContextRepository httpSessionSecurityContextRepository = new HttpSessionSecurityContextRepository();
return httpSessionSecurityContextRepository;
}
Может ли кто-нибудь помочь мне решить эту проблему?
Ответы
Ответ 1
Я попробовал решение Али Дехгани (в комментариях) следующим образом:
.sessionManagement().maximumSessions(1).and().invalidSessionUrl("/expired");
И как сказал Coder, добавьте "/expired"
в разрешенные URL-адреса и проблема будет решена. Спасибо всем, кто обратил внимание на мою проблему, особенно Али Дехгани и Кодер, за полезные комментарии.
Ответ 2
ConcurrentSessionFilter
будет перенаправлен на expiredUrl
, если valid идентификатор сеанса помечен как истек в SessionRegistry
, см. Spring Ссылка на безопасность:
- expired-url URL-адрес пользователя будет перенаправлен, если они попытаются использовать сеанс, который был "истек" контроллером параллельного сеанса, поскольку пользователь превысил количество разрешенных сеансов и снова вошел в систему в другом месте. Должен быть установлен, если не установлен exception-if-maximum-exceeded
. Если значение не указано, сообщение об истечении срока будет просто записано непосредственно обратно в ответ.
SessionManagementFilter
перенаправляется на invalidSessionUrl
, если идентификатор сеанса не valid (тайм-аут или неправильный идентификатор), см. Spring Ссылка на безопасность:
Если пользователь в настоящее время не аутентифицирован, фильтр проверяет, был ли запрошен неверный идентификатор сеанса (из-за тайм-аута, например), и вызывается настроенный InvalidSessionStrategy
, если он установлен. Наиболее распространенное поведение - это просто перенаправить на фиксированный URL-адрес, и он инкапсулирован в стандартную реализацию SimpleRedirectInvalidSessionStrategy
. Последнее также используется при настройке неверного URL-адреса сеанса через пространство имен, как описано ранее.
Оба URL (expiredUrl
, invalidSessionUrl
) должны быть настроены как permitAll()
.
BTW: Если вы хотите использовать Параллельный контроль сеанса с помощью maximumSessions
, вам нужно добавить HttpSessionEventPublisher
на ваш web.xml
:
Параллельный контроль сеанса
Если вы хотите установить ограничения на возможность доступа к одному пользователю для одного пользователя, Spring Security поддерживает это из коробки со следующими простыми дополнениями. Сначала вам нужно добавить следующего прослушивателя в ваш файл web.xml
, чтобы сохранить Spring Security обновленную информацию о событиях жизненного цикла сеанса:
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
Ответ 3
В идеале ваш UX должен просто перенаправить пользователя на страницу входа. Я предполагаю, что вы видите требование наличия выделенной/истекшей страницы из-за Spring MVC - изменение параметров безопасности динамически, где вы сообщили о необходимости иметь отдельные маски входа. Если обходной путь (тот, который я описал в ответе на ваш другой вопрос) работает для вас, вы можете отказаться от своего требования иметь страницу с выделенным/истекшим сроком действия и перенаправить пользователя на правильную страницу входа напрямую, используя номер подхода к решению ( 2). Как насчет этого?
Тем не менее, чтобы ответить на ваш текущий вопрос...
Я не уверен, что он работает, но попробуйте и измените свой код.
//...
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired");
}
to
//...
.sessionManagement().sessionFixation().newSession().maximumSessions(1)
.expiredUrl("/expired")
.sessionRegistry(sessionRegistry());
}
@Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
В случае, если это не сработает, можете ли вы затем отправить код своих customLogoutHandler()
и customLogoutSuccessHandler()
? Вы используете Spring MVC вне Spring Boot, правильно?
Ответ 4
Если вы используете UserDetails и UserDetailsService, тогда это должно быть потому, что в вашем классе реализации UserDetails нет метода Override hashCode() и equals (Object obj). Это мой класс реализации для UserDetails:
public class MyUser implements UserDetails {
private String username;
private String password;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public int hashCode() {
return username.hashCode();
}
@Override
public boolean equals(Object obj) {
return this.toString().equals(obj.toString());
}
}