Spring Boot Security和Vaadin页面导航和渲染问题

时间:2019-03-13 00:16:22

标签: java spring-boot vaadin

我有一个带有Vaadin的简单Spring Boot应用程序,用于UI和Spring Boot安全性。

我要实现的是从登录页面到主视图的组件之间的简单导航。

这是我的安全配置:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        // Not using Spring CSRF here to be able to use plain HTML for the login page
        http.csrf().disable()
                .authorizeRequests()
                .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
                .and().formLogin().loginPage(LOGIN_URL).permitAll().loginProcessingUrl(LOGIN_PROCESSING_URL)
                .failureUrl(LOGIN_FAILURE_URL)
                .successHandler(new SavedRequestAwareAuthenticationSuccessHandler())
                .and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL);
    }

这是我的LoginView:

@Route("login")
@UIScope
@SpringComponent
public class LoginView extends VerticalLayout {

/**
 * AuthenticationManager is already exposed in WebSecurityConfig
 */
@Autowired
private AuthenticationManager authManager;

private LoginOverlay loginOverlay;

public LoginView() {
    loginOverlay = new LoginOverlay();
    loginOverlay.addLoginListener(this::authenticate);
    loginOverlay.setOpened(true);

    LoginI18n i18n = LoginI18n.createDefault();
    i18n.setAdditionalInformation("Welcome");
    loginOverlay.setI18n(i18n);

    add(loginOverlay);
}

private void authenticate(AbstractLogin.LoginEvent e) {
    try {
        Authentication auth = authManager.authenticate(
                new UsernamePasswordAuthenticationToken(e.getUsername(), e.getPassword()));

        SecurityContext sc = SecurityContextHolder.getContext();
        sc.setAuthentication(auth);

        if (auth.isAuthenticated())
            getUI().ifPresent(ui -> ui.navigate(MainView.class));
    } catch (Exception ex) {
        loginOverlay.setError(true);
    }
}}

和MainView:

@Route("main")
public class MainView extends VerticalLayout implements AfterNavigationObserver {

    private final CertView certView;
    private final UserView userView;

    public MainView(CertView certView, UserView userView) {
        this.certView = certView;
        this.userView = userView;

    }

    private void createMain() {
        Tab tab1 = new Tab("Certificates");
        Tab tab2 = new Tab("Users");

        Tabs tabs = new Tabs(tab1, tab2);

        certView.setVisible(true);
        userView.setVisible(false);

        Map<Tab, Component> tabsToPages = new HashMap<>();
        tabsToPages.put(tab1, certView);
        tabsToPages.put(tab2, userView);

        Div pages = new Div(certView, userView);
        pages.setSizeFull();

        Set<Component> pagesShown = Stream.of(certView)
                .collect(Collectors.toSet());

        tabs.addSelectedChangeListener(event -> {
            pagesShown.forEach(page -> page.setVisible(false));
            pagesShown.clear();
            Component selectedPage = tabsToPages.get(tabs.getSelectedTab());
            selectedPage.setVisible(true);
            pagesShown.add(selectedPage);
        });

        add(tabs, pages);
    }


    @Override
    public void afterNavigation(AfterNavigationEvent afterNavigationEvent) {
        createMain();
    }
}

CertViewUserView@UIScope d个@SpringComponent,其中注入了一些DAO,并且正在数据中将其设置为正值。

现在,当登录视图的authenticateauthManager.authenticate被调用时会发生什么,就是将视图路由到MainView,通过看到构造函数被调用,URL更改但没有呈现任何内容,我可以看出来。奇怪的是, 当我在MainView的构造函数页面中设置断点时会成功呈现。

我对Vaadin还是很陌生,我不知道正确的导航应该是什么样子,以便您可以评论这样做的更好方法,但实际上我想保持简单。

那么,如何正确导航或在正确的生命周期事件中呈现mainView的内容?

Vaadin:13.0.1

1 个答案:

答案 0 :(得分:1)

我有同样的问题。在导航到另一条路线之前,我通过关闭loginOverlay解决了该问题。

if (auth.isAuthenticated())
{
  loginOverlay.close(); // <-- add this line!

  getUI().ifPresent(ui -> ui.navigate(MainView.class));
}