Java 弹簧靴安全与防护;Vaadin页面导航和;渲染问题

Java 弹簧靴安全与防护;Vaadin页面导航和;渲染问题,java,spring-boot,vaadin,Java,Spring Boot,Vaadin,我有一个简单的Spring Boot应用程序,它带有用于UI和Spring Boot安全性的Vaadin 我试图实现的是从登录页面到主视图的组件之间的简单导航 这是我的安全配置: @Override protected void configure(HttpSecurity http) throws Exception { // Not using Spring CSRF here to be able to use plain HTML for the login pa

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

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

这是我的安全配置:

@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);
    }
这是我的登录视图:

@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);
    }
}}
主要观点是:

@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();
    }
}
@Route(“main”)
公共类MainView扩展了垂直布局实现AfterNavigationObserver{
私人最终CertView CertView;
私有最终用户视图用户视图;
公共主视图(CertView CertView、UserView UserView){
this.certView=certView;
this.userView=userView;
}
私有void createMain(){
Tab tab1=新选项卡(“证书”);
Tab tab2=新选项卡(“用户”);
选项卡=新选项卡(选项卡1、选项卡2);
certView.setVisible(true);
setVisible(false);
Map tabsToPages=newhashmap();
tabsToPages.put(tab1,certView);
tabsToPages.put(tab2,userView);
Div pages=新Div(certView、userView);
pages.setSizeFull();
设置pagesShown=Stream.of(certView)
.collect(收集器.toSet());
tabs.addSelectedChangeListener(事件->{
pagesShown.forEach(page->page.setVisible(false));
pagesShown.clear();
Component selectedPage=tabsToPages.get(tabs.getSelectedTab());
selectedPage.setVisible(真);
页面显示添加(已选择页面);
});
添加(选项卡、页面);
}
@凌驾
公共无效afterNavigation(AfterNavigationEvent AfterNavigationEvent){
createMain();
}
}
CertView
UserView
@UIScope
d
@SpringComponent
s,它们注入了一些DAO,正在获取数据并将其组件设置在它们的共同构造函数中

现在,当登录视图的
authenticate
authManager.authenticate
被调用时,会发生什么情况?视图被路由到MainView,我可以通过看到调用构造函数来判断,url会发生变化,但不会呈现任何内容。奇怪的是,当我在MainView的构造函数页面中设置断点时,成功呈现。

我对Vaadin很陌生,我不知道正确的导航应该是什么样子,这样你就可以评论更好的方法,但实际上我希望尽可能简单

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


瓦丁:13.0.1

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

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

  getUI().ifPresent(ui -> ui.navigate(MainView.class));
}
if(auth.isAuthenticated())
{
loginOverlay.close();//ui.navigate(MainView.class));
}

您是否尝试调用
createMain()在构造函数中,而忽略AfterNavigationObserver?我不太清楚为什么你的版本不起作用,但是你可以通过不使用后导航来简化它。如果没有必要的话,当你想从url中读取一个参数时使用它是很好的。您的两个spring组件的注入应该仍然可以工作,并且像您在这里一样使用构造函数注入,注入的组件已经在构造函数中可用,因此没有必要将其延迟到@PostConstruct或AfterNavigation事件中。当然我已经尝试过了,这是相同的。。。