Vaadin security enhancements (#1003)

* Removed VaadinManagedSecurity configuration from MgmtUiAutoConfiguration
* added SessionFixationProtectionStrategy for additional protection of UI session authentication
* added VaadinSessionClosingLogoutHandler to logout from all UI sessions
* added AccessDecisionManager to UI security configuration in order to support method security in UI in context of VaadinSharedSecurity
* Changed UI push transport from WEBSOCKET to WEBSOCKET_XHR to solve problems with Spring Security Context
* Suppressed atmosphere IOUtils false-positive warning
* Removed obsolete AsyncVaadinServletConfiguration
* Defined Vaadin4SpringServlet bean instead of plain SpringVaadinServlet for configuration flexibility
* Removed obsolete SpringSecurityAtmosphereInterceptor because the client does not communicate with the server using websocket protocol anymore
* Removed unit test for SpringSecurityAtmosphereInterceptor
* Removed obsolete AuthenticationManagerConfigurer coming from Vaadin Managed Security in InMemoryUserManagementAutoConfiguration
* Removed SessionFixationProtectionStrategy and VaadinSessionClosingLogoutHandler because all wrapper sessions are invalidated when the session managed by Spring gets invalidated together with configured HttpSessionEventPublisher events
* Added call to close the current session before logout redirect
* added comment why we used WEBSOCKET_XHR instead of WEBSOCKET

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io>
This commit is contained in:
Bondar Bogdan
2020-09-03 10:35:22 +02:00
committed by GitHub
parent fe8569593e
commit 0e4b67895e
11 changed files with 84 additions and 224 deletions

View File

@@ -29,7 +29,6 @@ import org.springframework.context.annotation.Import;
import org.vaadin.spring.annotation.EnableVaadinExtensions;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.annotation.EnableEventBus;
import org.vaadin.spring.security.annotation.EnableVaadinManagedSecurity;
import com.vaadin.spring.annotation.UIScope;
@@ -37,7 +36,6 @@ import com.vaadin.spring.annotation.UIScope;
* The Management UI auto configuration.
*/
@Configuration
@EnableVaadinManagedSecurity
@EnableVaadinExtensions
@EnableEventBus
@ConditionalOnClass(MgmtUiConfiguration.class)
@@ -114,5 +112,4 @@ public class MgmtUiAutoConfiguration {
return delayedEventBusPushStrategy;
}
}

View File

@@ -32,7 +32,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.vaadin.spring.security.config.AuthenticationManagerConfigurer;
/**
* Auto-configuration for the in-memory-user-management.
@@ -41,8 +40,7 @@ import org.vaadin.spring.security.config.AuthenticationManagerConfigurer;
@Configuration
@ConditionalOnMissingBean(UserDetailsService.class)
@EnableConfigurationProperties({ MultiUserProperties.class })
public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticationConfigurerAdapter
implements AuthenticationManagerConfigurer {
public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticationConfigurerAdapter {
private static final String DEFAULT_TENANT = "DEFAULT";
@@ -93,8 +91,7 @@ public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticatio
final String name = securityProperties.getUser().getName();
final String password = securityProperties.getUser().getPassword();
final List<String> roles = securityProperties.getUser().getRoles();
List<GrantedAuthority> authorityList = roles.isEmpty()
? PermissionUtils.createAllAuthorityList()
final List<GrantedAuthority> authorityList = roles.isEmpty() ? PermissionUtils.createAllAuthorityList()
: createAuthoritiesFromList(roles);
userPrincipals
.add(new UserPrincipal(name, password, name, name, name, null, DEFAULT_TENANT, authorityList));
@@ -104,7 +101,7 @@ public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticatio
}
private static List<GrantedAuthority> createAuthoritiesFromList(final List<String> userAuthorities) {
List<GrantedAuthority> grantedAuthorityList = new ArrayList<>(userAuthorities.size());
final List<GrantedAuthority> grantedAuthorityList = new ArrayList<>(userAuthorities.size());
for (final String permission : userAuthorities) {
grantedAuthorityList.add(new SimpleGrantedAuthority(permission));
grantedAuthorityList.add(new SimpleGrantedAuthority("ROLE_" + permission));
@@ -154,7 +151,7 @@ public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticatio
final Authentication authentication, final UserDetails user) {
final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
authentication.getCredentials(), user.getAuthorities());
result.setDetails(new TenantAwareAuthenticationDetails("DEFAULT", false));
result.setDetails(new TenantAwareAuthenticationDetails(DEFAULT_TENANT, false));
return result;
}
}

View File

@@ -60,11 +60,13 @@ import org.springframework.context.annotation.PropertySource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
@@ -595,6 +597,7 @@ public class SecurityManagedConfiguration {
*/
@Configuration
@Order(400)
@EnableWebSecurity
@EnableVaadinSharedSecurity
@ConditionalOnClass(MgmtUiConfiguration.class)
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@@ -714,7 +717,6 @@ public class SecurityManagedConfiguration {
// UI logout
httpSec.logout().logoutUrl("/UI/logout*").addLogoutHandler(logoutHandler)
.logoutSuccessHandler(logoutSuccessHandler);
}
@Override
@@ -722,8 +724,25 @@ public class SecurityManagedConfiguration {
// No security for static content
webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/docs/**");
}
}
/**
* Configuration that defines the {@link AccessDecisionManager} bean for
* UI method security used by the Vaadin Servlet. Notice: we can not use
* the top-level method security configuration because
* {@link AdviceMode.ASPECTJ} is not supported.
*/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
@ConditionalOnClass(MgmtUiConfiguration.class)
static class UIMethodSecurity extends GlobalMethodSecurityConfiguration {
@Bean(name = VaadinSharedSecurityConfiguration.ACCESS_DECISION_MANAGER_BEAN)
@Override
protected AccessDecisionManager accessDecisionManager() {
return super.accessDecisionManager();
}
}
}
}
/**