Vaadin8+SpringBoot集成SpringSecurity配置技术咨询
Hey there, I’ve tackled this exact setup before—Vaadin 8 + Spring Boot + Spring Security with pure annotation-based config is totally feasible, no XML, no vaadin4Spring, no external login.html or Spring MVC login pages required. Let’s walk through the step-by-step implementation:
First, lock in compatible versions—Vaadin 8 works best with Spring Boot 2.3.x (newer versions have compatibility gaps). Here’s the Maven setup:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-spring-boot-starter</artifactId> <version>8.14.3</version> <!-- Latest stable Vaadin 8 release --> </dependency> </dependencies>
This class handles all security rules, login/logout flow, and permission controls—no XML needed:
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // Example in-memory users—replace with your custom UserDetailsService for production auth.inMemoryAuthentication() .passwordEncoder(new BCryptPasswordEncoder()) .withUser("user") .password(new BCryptPasswordEncoder().encode("password")) .roles("USER") .and() .withUser("admin") .password(new BCryptPasswordEncoder().encode("admin")) .roles("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http // Disable Spring Security CSRF—Vaadin manages its own CSRF tokens internally .csrf().disable() // Define access rules .authorizeRequests() // Allow Vaadin static resources and login page without authentication .antMatchers("/VAADIN/**", "/login", "/login/**").permitAll() // All other requests require authentication .anyRequest().authenticated() .and() // Configure form login to use our Vaadin LoginUI .formLogin() .loginPage("/login") // Spring Security handles authentication at this endpoint .loginProcessingUrl("/perform_login") // Redirect to MainUI after successful login .defaultSuccessUrl("/", true) .permitAll() .and() // Configure logout flow .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login?logout") .permitAll(); } }
This is your /login path UI, built entirely with Vaadin components—no external HTML:
import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; import com.vaadin.server.VaadinRequest; import com.vaadin.spring.annotation.SpringUI; import com.vaadin.ui.*; import com.vaadin.ui.themes.ValoTheme; @SpringUI(path = "/login") @Theme("valo") @Title("Application Login") public class LoginUI extends UI { @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); layout.setSizeFull(); layout.setMargin(true); layout.setSpacing(true); layout.setDefaultComponentAlignment(Alignment.MIDDLE_CENTER); // Login form FormLayout formLayout = new FormLayout(); formLayout.setSpacing(true); TextField usernameField = new TextField("Username"); usernameField.setWidth("300px"); usernameField.setRequiredIndicatorVisible(true); usernameField.setId("username"); // Matches Spring Security's default parameter name PasswordField passwordField = new PasswordField("Password"); passwordField.setWidth("300px"); passwordField.setRequiredIndicatorVisible(true); passwordField.setId("password"); // Matches Spring Security's default parameter name Button loginButton = new Button("Login"); loginButton.setWidth("100%"); loginButton.addStyleName(ValoTheme.BUTTON_PRIMARY); // Handle login button click loginButton.addClickListener(event -> { if (usernameField.isEmpty() || passwordField.isEmpty()) { Notification.show("Please fill all fields", Notification.Type.WARNING_MESSAGE); return; } // Submit credentials to Spring Security's authentication endpoint getPage().setLocation("/perform_login?username=" + usernameField.getValue() + "&password=" + passwordField.getValue()); }); formLayout.addComponents(usernameField, passwordField, loginButton); layout.addComponent(formLayout); // Show logout success message if coming from logout if (vaadinRequest.getParameter("logout") != null) { Notification.show("You've been logged out successfully", Notification.Type.HUMANIZED_MESSAGE); } setContent(layout); } }
This is your root path UI, with a SpringNavigator to manage multiple @SpringView components:
import com.vaadin.annotations.Theme; import com.vaadin.server.VaadinRequest; import com.vaadin.spring.annotation.SpringUI; import com.vaadin.spring.navigator.SpringNavigator; import com.vaadin.ui.*; import org.springframework.beans.factory.annotation.Autowired; @SpringUI(path = "") @Theme("valo") public class MainUI extends UI { private final SpringNavigator navigator; @Autowired public MainUI(SpringNavigator navigator) { this.navigator = navigator; } @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout mainLayout = new VerticalLayout(); mainLayout.setSizeFull(); mainLayout.setMargin(false); mainLayout.setSpacing(false); // Header with logout button HorizontalLayout header = new HorizontalLayout(); header.setWidth("100%"); header.setPadding(true); header.addComponent(new Label("My Vaadin 8 App")); Button logoutBtn = new Button("Logout"); logoutBtn.addClickListener(event -> getPage().setLocation("/logout")); header.addComponent(logoutBtn); header.setComponentAlignment(logoutBtn, Alignment.MIDDLE_RIGHT); header.setExpandRatio(header.getComponent(0), 1); // View display container Panel viewPanel = new Panel(); viewPanel.setSizeFull(); mainLayout.addComponents(header, viewPanel); mainLayout.setExpandRatio(viewPanel, 1); setContent(mainLayout); // Initialize navigator to manage views in the panel navigator.init(this, viewPanel); } }
Example Spring Views
Just annotate your views with @SpringView—they’ll auto-register with the navigator:
import com.vaadin.spring.annotation.SpringView; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; @SpringView(name = DashboardView.VIEW_NAME) public class DashboardView extends VerticalLayout { public static final String VIEW_NAME = "dashboard"; public DashboardView() { addComponent(new Label("Welcome to the Dashboard!")); setSizeFull(); setDefaultComponentAlignment(Alignment.MIDDLE_CENTER); } }
import com.vaadin.spring.annotation.SpringView; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; @SpringView(name = ProfileView.VIEW_NAME) public class ProfileView extends VerticalLayout { public static final String VIEW_NAME = "profile"; public ProfileView() { addComponent(new Label("Your Profile Details")); setSizeFull(); setDefaultComponentAlignment(Alignment.MIDDLE_CENTER); } }
- Version Compatibility: Stick to Spring Boot 2.3.x with Vaadin 8—newer Spring Boot versions break Vaadin 8’s Spring integration.
- CSRF Safety: We disable Spring Security’s CSRF because Vaadin handles its own CSRF tokens, so you’re not sacrificing security.
- View Access: Once a user is authenticated, they can access all
@SpringViewcomponents in MainUI—add method-level security with@PreAuthorizeif you need granular control.
内容的提问来源于stack exchange,提问作者David B

