Я интегрировал свой проект Vaadin с Spring Security, поэтому у меня возникла проблема с управлением сессиями.В частности, с одновременным управлением сессиями.При этом пользователю разрешено входить в разные браузеры на одном ПК.Прилагается моя конфигурация и класс, который расширяет AbstractSecurityWebApplicationInitializer.
Вот мой класс конфигурации.
@EnableWebSecurity(debug = true)
@Configuration
@ComponentScan(basePackages = { "com.pnb" })
@EnableVaadin
@EnableVaadinNavigation
@PropertySource(value = "classpath:abo.properties")
public class ABOConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("authUserDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
// HttpSecurity httpSec = http.regexMatcher("(?!.*HEARTBEAT)^.*\\/UI.*$")
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/APP/**", "/VAADIN/**", "/HEARTBEAT/**", "/UIDL/**", "/resources/**", "/login",
"/login**", "/login/**", "/application")
.permitAll()
.anyRequest()
.authenticated()
.antMatchers("/**")
.access("hasRole('ROLE')")
.and()
.requiresChannel()
.anyRequest()
.requiresSecure()
.and()
.exceptionHandling()
.and()
.formLogin()
.loginPage("/login?auth")
.defaultSuccessUrl("/application", true)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "PUT"))
.logoutSuccessUrl("/login?auth")
.clearAuthentication(true)
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.and().headers().frameOptions().sameOrigin()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).sessionAuthenticationErrorUrl("/login/?auth")
.sessionFixation().changeSessionId()
.sessionAuthenticationStrategy(sessionAuthenticationStrategy())
.invalidSessionUrl("/login/?auth")
.maximumSessions(1).maxSessionsPreventsLogin(true).sessionRegistry(this.sessionRegistry())
.expiredUrl("/login?auth")
;
}
/* @Bean
@Qualifier("httpSessionEventPublisher")
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}*/
@Bean
public Filter vaadinSessionRewriteFilter() {
return new VaadinSessionRewriteFilter();
}
@Bean
public SecurityContextHolder securityContextHolder(){
SecurityContextHolder securityContextHolder = new SecurityContextHolder();
return securityContextHolder;
}
@Bean
protected SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(12);
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
@Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
@Bean
public IWebClient getWebClient() {
return WebClientFactory.getInstance();
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public static SendEmailService sendEmailService(){
return new SendEmailService();
}
@Bean
public ConcurrentSessionControlAuthenticationStrategy concurrenSessionControlStrategy() {
ConcurrentSessionControlAuthenticationStrategy concurrenSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(
this.sessionRegistry());
concurrenSessionControlStrategy.setMaximumSessions(1);
concurrenSessionControlStrategy.setExceptionIfMaximumExceeded(true);
return concurrenSessionControlStrategy;
}
@Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy(){
RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy = new RegisterSessionAuthenticationStrategy(this.sessionRegistry());
return registerSessionAuthenticationStrategy;
}
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy(){
List<SessionAuthenticationStrategy> strategies = new LinkedList<>();
strategies.add(concurrenSessionControlStrategy());
strategies.add(registerSessionAuthenticationStrategy());
CompositeSessionAuthenticationStrategy compositeSessionAuthenticationStrategy = new CompositeSessionAuthenticationStrategy(strategies);
return compositeSessionAuthenticationStrategy;
}
}
Здесь мой класс, который расширяет AbstractSecurityWebApplicationInitializer.
@WebListener
@EnableVaadin
@Configuration
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer implements HttpSessionListener{
private static final Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
private final static Logger log = Logger.getLogger(MethodHandles.lookup().lookupClass());
public SecurityWebApplicationInitializer() {
super(ABOConfiguration.class, Config.class);
log.debug("ENABLE HTTPSESSION EVENT PUBLISHER "+enableHttpSessionEventPublisher());
}
@Override
protected boolean enableHttpSessionEventPublisher() {
// this method changed everything for me
return true;
}
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
sessions.put(session.getId(), session);
}
public void sessionDestroyed(HttpSessionEvent event) {
sessions.remove(event.getSession().getId());
}
public static HttpSession find(String sessionId) {
return sessions.get(sessionId);
}
public static Map<String, HttpSession> getSessions() {
return sessions;
}
}