"Can't move a node from one state tree to another" 注销时
"Can't move a node from one state tree to another" when logging out
我正在使用 vaadin 应用程序,但在我尝试注销时一直收到此错误。我尝试了很多方法来阻止这种情况,但真的不知道该怎么做:
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
at com.vaadin.flow.internal.StateNode.doSetTree(StateNode.java:684) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.lambda$setTree(StateNode.java:364) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.visitNodeTree(StateNode.java:643) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.setTree(StateNode.java:364) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:264) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.NodeFeature.attachPotentialChild(NodeFeature.java:78) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.add(StateNodeNodeList.java:53) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.ElementChildrenList.add(ElementChildrenList.java:42) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.insertChild(AbstractNodeStateProvider.java:102) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.Node.insertChild(Node.java:250) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.Node.appendChild(Node.java:141) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.component.internal.UIInternals.showRouteTarget(UIInternals.java:730) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:240) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.handleNavigation(Router.java:223) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.navigate(Router.java:194) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.initializeUI(Router.java:92) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.BootstrapHandler.createAndInitUI(BootstrapHandler.java:1489) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest(BootstrapHandler.java:459) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1540) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:95) ~[vaadin-spring-12.1.2.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
每当我单击注销时,我都会成功重定向到登录视图,但它没有登录,而是显示 "Assertion Error: No child Node found with id -1" 并且我收到了上述错误。很少有描述。
这是我的登录视图 Class:
@Route(value = "login")
public class LoginView extends LoginOverlay implements BeforeEnterObserver, AfterNavigationObserver {
public LoginView() {
LoginI18n i18n = LoginI18n.createDefault();
i18n.setHeader(new LoginI18n.Header());
i18n.getHeader().setTitle("FBLA Genie");
i18n.getHeader().setDescription("Login to the FBLA Genie App");
i18n.setAdditionalInformation(null);
i18n.setForm(new LoginI18n.Form());
i18n.getForm().setSubmit("Sign in");
i18n.getForm().setTitle("FBLA Genie");
i18n.getForm().setUsername("Username/ID");
i18n.getForm().setPassword("Password");
setI18n(i18n);
setAction("login");
setForgotPasswordButtonVisible(false);
}
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
if (SecurityUtils.isUserLoggedIn()) {
beforeEnterEvent.forwardTo(Home.class);
} else {
setOpened(true);
}
}
@Override
public void afterNavigation(AfterNavigationEvent event) {
setError(
event.getLocation().getQueryParameters().getParameters().containsKey(
"error"));
}
}
我的安全配置:
@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String LOGIN_PROCESSING_URL = "/login";
private static final String LOGIN_FAILURE_URL = "/login?error";
private static final String LOGIN_URL = "/login";
private static final String LOGOUT_SUCCESS_URL = "/login";
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestCache().requestCache(new CustomRequestCache())
.and().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);
}
/**
* Configures the Login Information and credentials to the app.
* <p>
* Currently using temporary security for demonstration purposes.
*/
@Bean
@Override
/*
* Can be made more secure with this
* https://dzone.com/articles/spring-security-authentication
*/
public UserDetailsService userDetailsService() {
UserDetails admin...
return new InMemoryUserDetailsManager(admin);
}
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(
...
}
}
我的 SecurityUtils:
/**
* A Class for Util methods in security
*/
public final class SecurityUtils {
private SecurityUtils() {
// Util methods only
}
static boolean isFrameworkInternalRequest(HttpServletRequest request) {
final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER);
return parameterValue != null
&& Stream.of(ServletHelper.RequestType.values())
.anyMatch(r -> r.getIdentifier().equals(parameterValue));
}
public static boolean isUserLoggedIn() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication != null
&& !(authentication instanceof AnonymousAuthenticationToken)
&& authentication.isAuthenticated();
}
public static boolean isAccessGranted(Class<?> securedClass) {
//Allows if there are no roles required
Secured secured = AnnotationUtils.findAnnotation(securedClass, Secured.class);
if (secured == null) return true;
//looks up role options
List<String> allowedRoles = Arrays.asList(secured.value());
Authentication userAuthentication = SecurityContextHolder.getContext().getAuthentication();
return userAuthentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(allowedRoles::contains);
}
}
我的自定义请求缓存:
class CustomRequestCache extends HttpSessionRequestCache {
@Override
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
if (!SecurityUtils.isFrameworkInternalRequest(request)) {
super.saveRequest(request, response);
}
}
}
我的 ConfigureUIServiceInitListener:
@Component
public class ConfigureUIServiceInitListener implements VaadinServiceInitListener {
@Override
public void serviceInit(ServiceInitEvent event) {
event.getSource().addUIInitListener(uiEvent -> { //
final UI ui = uiEvent.getUI();
ui.addBeforeEnterListener(this::beforeEnter);
});
}
private void beforeEnter(BeforeEnterEvent event) {
if (!SecurityUtils.isAccessGranted(event.getNavigationTarget())) {
if (SecurityUtils.isUserLoggedIn()) {
event.rerouteToError(NotFoundException.class);
} else {
event.rerouteTo(LoginView.class);
}
}
}
}
我的主视图
@PWA(name = "",
shortName = "",
description = "This is the Application made by Shourya Bansal")
@PreserveOnRefresh
@UIScope
public class MainView extends AppLayout {
public static final Tab HOME_TAB = createTab(VaadinIcon.HOME, "Home", Home.class);
public static final Tab ADD_STUDENT_TAB = createTab(VaadinIcon.FILE_ADD, "Add a Student", CreateStudent.class);
public static final Tab ADD_HOURS_TAB = createTab(VaadinIcon.EDIT, "Add Hours to Student", AddHours.class);
public static final Tab VIEW_EDIT_TAB = createTab(VaadinIcon.EYE, "View and Edit Students", GetStudentInformation.class);
public static final Tab REPORT_TAB = createTab(VaadinIcon.RECORDS, "Generate Reports", Reports.class);
public static final Tab MAIL_TAB = createTab(VaadinIcon.MAILBOX, "Send Message", MailView.class);
public static final Tab DOC_TAB = createTab(VaadinIcon.QUESTION, "Documentation and FAQs", Documentation.class);
public static final Tabs tabs = getTabs();
public MainView() {
final Tabs tabs = new Tabs();
//Uses Tabs for Navigation
tabs.setOrientation(Tabs.Orientation.HORIZONTAL);
tabs.add(getAvailableTabs());
tabs.setFlexGrowForEnclosedTabs(1);
Image logo = new Image("https://github.com/Mastermind497/Shourya_FBLA/raw/master/logo/Logo.png", "Logo");
logo.setHeight("12em");
Button toGitHubPage = new Button("Go To GitHub Page");
toGitHubPage.addClickListener(buttonClickEvent -> UI.getCurrent().getPage().executeJs("window.open(\"https://github.com/Mastermind497/Shourya_FBLA\", \"_blank\", \"\");"));
//A Button for Toggling Dark Mode
final Button toggleButton = new Button("Dark Mode", VaadinIcon.MOON.create());
toggleButton.addClickListener(click -> {
ThemeList themeList = UI.getCurrent().getElement().getThemeList();
if (themeList.contains(Lumo.DARK)) {
themeList.remove(Lumo.DARK);
toggleButton.setText("Dark Mode");
toggleButton.setIcon(VaadinIcon.MOON.create());
} else {
themeList.add(Lumo.DARK);
toggleButton.setText("Light Mode");
toggleButton.setIcon(VaadinIcon.SUN_O.create());
}
});
HorizontalLayout buttons = new HorizontalLayout(toGitHubPage, toggleButton);
//Creates a Vertical Layout to store all the above components
VerticalLayout verticalLayout = new VerticalLayout();
//Adds component to Vertical Layout
verticalLayout.setSizeFull();
verticalLayout.add(logo);
verticalLayout.add(buttons);
verticalLayout.add(tabs);
//Aligns everything to the center
verticalLayout.setAlignItems(FlexComponent.Alignment.CENTER);
//Checks to see if main database is made. Makes if not
MySQLMethods.setUp();
addToNavbar(verticalLayout);
this.setDrawerOpened(false);
}
/**
* Generates the tabs for the Navbar
*
* @return The Tabs for the navBar
*/
public static Tabs getTabs() {
return new Tabs(getAvailableTabs());
}
/**
* Creates an ArrayList of the Tabs for Each page
*
* @return The Tabs
*/
private static Tab[] getAvailableTabs() {
final ArrayList<Tab> tabs = new ArrayList<>(7);
tabs.add(HOME_TAB);
tabs.add(ADD_STUDENT_TAB);
tabs.add(ADD_HOURS_TAB);
tabs.add(VIEW_EDIT_TAB);
tabs.add(REPORT_TAB);
tabs.add(MAIL_TAB);
tabs.add(DOC_TAB);
tabs.add(createTab(createLogoutLink()));
return tabs.toArray(new Tab[0]);
}
private static Anchor createLogoutLink() {
final Anchor a = populateLink(new Anchor(), VaadinIcon.LOCK, "Log Out");
a.setHref("/logout");
return a;
}
private static Tab createTab(VaadinIcon icon, String title, Class<? extends Component> viewClass) {
RouterLink routerLink = new RouterLink(null, viewClass);
routerLink.setHighlightCondition(HighlightConditions.sameLocation());
return createTab(populateLink(routerLink, icon, title));
}
private static Tab createTab(Component content) {
final Tab tab = new Tab();
tab.addThemeVariants(TabVariant.LUMO_ICON_ON_TOP);
tab.add(content);
return tab;
}
private static <T extends HasComponents> T populateLink(T a, VaadinIcon icon, String title) {
a.add(icon.create());
a.add(title);
return a;
}
}
我的登录视图
/**
* A Class that allows logging in to the system. Huge potential for security, currently not using
* its full capabilities for demonstration purposes.
*/
@Route(value = "login")
@PageTitle("Login | FBLA Genie")
@PreserveOnRefresh
@UIScope
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
/**
* The main login form
*/
final LoginForm login = new LoginForm();
/**
* Sets up the Login View and adds it to the its page
*/
public LoginView() {
addClassName("login-view");
setSizeFull();
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
setAlignItems(FlexComponent.Alignment.CENTER);
login.setAction("login");
Image logo = new Image("https://github.com/Mastermind497/Shourya_FBLA/raw/master/logo/Logo.png", "Logo");
logo.setHeight("24em");
add(
logo,
login
);
}
/**
* Turns on security, preventing access to the rest of the app before login is complete
*
* @param beforeEnterEvent A lambda event that is used by the login view to validate if the app should
* be open or remain closed
*/
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
//Checks whether there is a parameter error
if (!beforeEnterEvent.getLocation()
.getQueryParameters()
.getParameters()
.getOrDefault("error", Collections.emptyList())
.isEmpty()) {
//makes error visible
login.setError(true);
}
}
}
它已经被团队修复,应该会在下一个小版本中发布。 (我猜它会是 14.2.1)。目前,作为解决方法,您可以删除注释
Vaadin 也不支持在静态字段中存储组件。就我而言,这就是问题所在。 (Vaadin 18).
我正在使用 vaadin 应用程序,但在我尝试注销时一直收到此错误。我尝试了很多方法来阻止这种情况,但真的不知道该怎么做:
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
at com.vaadin.flow.internal.StateNode.doSetTree(StateNode.java:684) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.lambda$setTree(StateNode.java:364) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.visitNodeTree(StateNode.java:643) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.setTree(StateNode.java:364) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:264) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.NodeFeature.attachPotentialChild(NodeFeature.java:78) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.add(StateNodeNodeList.java:53) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.internal.nodefeature.ElementChildrenList.add(ElementChildrenList.java:42) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.insertChild(AbstractNodeStateProvider.java:102) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.Node.insertChild(Node.java:250) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.dom.Node.appendChild(Node.java:141) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.component.internal.UIInternals.showRouteTarget(UIInternals.java:730) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:240) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.handleNavigation(Router.java:223) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.navigate(Router.java:194) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.router.Router.initializeUI(Router.java:92) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.BootstrapHandler.createAndInitUI(BootstrapHandler.java:1489) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest(BootstrapHandler.java:459) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1540) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.1.3.jar:2.1.3]
at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:95) ~[vaadin-spring-12.1.2.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
每当我单击注销时,我都会成功重定向到登录视图,但它没有登录,而是显示 "Assertion Error: No child Node found with id -1" 并且我收到了上述错误。很少有描述。
这是我的登录视图 Class:
@Route(value = "login")
public class LoginView extends LoginOverlay implements BeforeEnterObserver, AfterNavigationObserver {
public LoginView() {
LoginI18n i18n = LoginI18n.createDefault();
i18n.setHeader(new LoginI18n.Header());
i18n.getHeader().setTitle("FBLA Genie");
i18n.getHeader().setDescription("Login to the FBLA Genie App");
i18n.setAdditionalInformation(null);
i18n.setForm(new LoginI18n.Form());
i18n.getForm().setSubmit("Sign in");
i18n.getForm().setTitle("FBLA Genie");
i18n.getForm().setUsername("Username/ID");
i18n.getForm().setPassword("Password");
setI18n(i18n);
setAction("login");
setForgotPasswordButtonVisible(false);
}
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
if (SecurityUtils.isUserLoggedIn()) {
beforeEnterEvent.forwardTo(Home.class);
} else {
setOpened(true);
}
}
@Override
public void afterNavigation(AfterNavigationEvent event) {
setError(
event.getLocation().getQueryParameters().getParameters().containsKey(
"error"));
}
}
我的安全配置:
@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String LOGIN_PROCESSING_URL = "/login";
private static final String LOGIN_FAILURE_URL = "/login?error";
private static final String LOGIN_URL = "/login";
private static final String LOGOUT_SUCCESS_URL = "/login";
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestCache().requestCache(new CustomRequestCache())
.and().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);
}
/**
* Configures the Login Information and credentials to the app.
* <p>
* Currently using temporary security for demonstration purposes.
*/
@Bean
@Override
/*
* Can be made more secure with this
* https://dzone.com/articles/spring-security-authentication
*/
public UserDetailsService userDetailsService() {
UserDetails admin...
return new InMemoryUserDetailsManager(admin);
}
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(
...
}
}
我的 SecurityUtils:
/**
* A Class for Util methods in security
*/
public final class SecurityUtils {
private SecurityUtils() {
// Util methods only
}
static boolean isFrameworkInternalRequest(HttpServletRequest request) {
final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER);
return parameterValue != null
&& Stream.of(ServletHelper.RequestType.values())
.anyMatch(r -> r.getIdentifier().equals(parameterValue));
}
public static boolean isUserLoggedIn() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication != null
&& !(authentication instanceof AnonymousAuthenticationToken)
&& authentication.isAuthenticated();
}
public static boolean isAccessGranted(Class<?> securedClass) {
//Allows if there are no roles required
Secured secured = AnnotationUtils.findAnnotation(securedClass, Secured.class);
if (secured == null) return true;
//looks up role options
List<String> allowedRoles = Arrays.asList(secured.value());
Authentication userAuthentication = SecurityContextHolder.getContext().getAuthentication();
return userAuthentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(allowedRoles::contains);
}
}
我的自定义请求缓存:
class CustomRequestCache extends HttpSessionRequestCache {
@Override
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
if (!SecurityUtils.isFrameworkInternalRequest(request)) {
super.saveRequest(request, response);
}
}
}
我的 ConfigureUIServiceInitListener:
@Component
public class ConfigureUIServiceInitListener implements VaadinServiceInitListener {
@Override
public void serviceInit(ServiceInitEvent event) {
event.getSource().addUIInitListener(uiEvent -> { //
final UI ui = uiEvent.getUI();
ui.addBeforeEnterListener(this::beforeEnter);
});
}
private void beforeEnter(BeforeEnterEvent event) {
if (!SecurityUtils.isAccessGranted(event.getNavigationTarget())) {
if (SecurityUtils.isUserLoggedIn()) {
event.rerouteToError(NotFoundException.class);
} else {
event.rerouteTo(LoginView.class);
}
}
}
}
我的主视图
@PWA(name = "",
shortName = "",
description = "This is the Application made by Shourya Bansal")
@PreserveOnRefresh
@UIScope
public class MainView extends AppLayout {
public static final Tab HOME_TAB = createTab(VaadinIcon.HOME, "Home", Home.class);
public static final Tab ADD_STUDENT_TAB = createTab(VaadinIcon.FILE_ADD, "Add a Student", CreateStudent.class);
public static final Tab ADD_HOURS_TAB = createTab(VaadinIcon.EDIT, "Add Hours to Student", AddHours.class);
public static final Tab VIEW_EDIT_TAB = createTab(VaadinIcon.EYE, "View and Edit Students", GetStudentInformation.class);
public static final Tab REPORT_TAB = createTab(VaadinIcon.RECORDS, "Generate Reports", Reports.class);
public static final Tab MAIL_TAB = createTab(VaadinIcon.MAILBOX, "Send Message", MailView.class);
public static final Tab DOC_TAB = createTab(VaadinIcon.QUESTION, "Documentation and FAQs", Documentation.class);
public static final Tabs tabs = getTabs();
public MainView() {
final Tabs tabs = new Tabs();
//Uses Tabs for Navigation
tabs.setOrientation(Tabs.Orientation.HORIZONTAL);
tabs.add(getAvailableTabs());
tabs.setFlexGrowForEnclosedTabs(1);
Image logo = new Image("https://github.com/Mastermind497/Shourya_FBLA/raw/master/logo/Logo.png", "Logo");
logo.setHeight("12em");
Button toGitHubPage = new Button("Go To GitHub Page");
toGitHubPage.addClickListener(buttonClickEvent -> UI.getCurrent().getPage().executeJs("window.open(\"https://github.com/Mastermind497/Shourya_FBLA\", \"_blank\", \"\");"));
//A Button for Toggling Dark Mode
final Button toggleButton = new Button("Dark Mode", VaadinIcon.MOON.create());
toggleButton.addClickListener(click -> {
ThemeList themeList = UI.getCurrent().getElement().getThemeList();
if (themeList.contains(Lumo.DARK)) {
themeList.remove(Lumo.DARK);
toggleButton.setText("Dark Mode");
toggleButton.setIcon(VaadinIcon.MOON.create());
} else {
themeList.add(Lumo.DARK);
toggleButton.setText("Light Mode");
toggleButton.setIcon(VaadinIcon.SUN_O.create());
}
});
HorizontalLayout buttons = new HorizontalLayout(toGitHubPage, toggleButton);
//Creates a Vertical Layout to store all the above components
VerticalLayout verticalLayout = new VerticalLayout();
//Adds component to Vertical Layout
verticalLayout.setSizeFull();
verticalLayout.add(logo);
verticalLayout.add(buttons);
verticalLayout.add(tabs);
//Aligns everything to the center
verticalLayout.setAlignItems(FlexComponent.Alignment.CENTER);
//Checks to see if main database is made. Makes if not
MySQLMethods.setUp();
addToNavbar(verticalLayout);
this.setDrawerOpened(false);
}
/**
* Generates the tabs for the Navbar
*
* @return The Tabs for the navBar
*/
public static Tabs getTabs() {
return new Tabs(getAvailableTabs());
}
/**
* Creates an ArrayList of the Tabs for Each page
*
* @return The Tabs
*/
private static Tab[] getAvailableTabs() {
final ArrayList<Tab> tabs = new ArrayList<>(7);
tabs.add(HOME_TAB);
tabs.add(ADD_STUDENT_TAB);
tabs.add(ADD_HOURS_TAB);
tabs.add(VIEW_EDIT_TAB);
tabs.add(REPORT_TAB);
tabs.add(MAIL_TAB);
tabs.add(DOC_TAB);
tabs.add(createTab(createLogoutLink()));
return tabs.toArray(new Tab[0]);
}
private static Anchor createLogoutLink() {
final Anchor a = populateLink(new Anchor(), VaadinIcon.LOCK, "Log Out");
a.setHref("/logout");
return a;
}
private static Tab createTab(VaadinIcon icon, String title, Class<? extends Component> viewClass) {
RouterLink routerLink = new RouterLink(null, viewClass);
routerLink.setHighlightCondition(HighlightConditions.sameLocation());
return createTab(populateLink(routerLink, icon, title));
}
private static Tab createTab(Component content) {
final Tab tab = new Tab();
tab.addThemeVariants(TabVariant.LUMO_ICON_ON_TOP);
tab.add(content);
return tab;
}
private static <T extends HasComponents> T populateLink(T a, VaadinIcon icon, String title) {
a.add(icon.create());
a.add(title);
return a;
}
}
我的登录视图
/**
* A Class that allows logging in to the system. Huge potential for security, currently not using
* its full capabilities for demonstration purposes.
*/
@Route(value = "login")
@PageTitle("Login | FBLA Genie")
@PreserveOnRefresh
@UIScope
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
/**
* The main login form
*/
final LoginForm login = new LoginForm();
/**
* Sets up the Login View and adds it to the its page
*/
public LoginView() {
addClassName("login-view");
setSizeFull();
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
setAlignItems(FlexComponent.Alignment.CENTER);
login.setAction("login");
Image logo = new Image("https://github.com/Mastermind497/Shourya_FBLA/raw/master/logo/Logo.png", "Logo");
logo.setHeight("24em");
add(
logo,
login
);
}
/**
* Turns on security, preventing access to the rest of the app before login is complete
*
* @param beforeEnterEvent A lambda event that is used by the login view to validate if the app should
* be open or remain closed
*/
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
//Checks whether there is a parameter error
if (!beforeEnterEvent.getLocation()
.getQueryParameters()
.getParameters()
.getOrDefault("error", Collections.emptyList())
.isEmpty()) {
//makes error visible
login.setError(true);
}
}
}
它已经被团队修复,应该会在下一个小版本中发布。 (我猜它会是 14.2.1)。目前,作为解决方法,您可以删除注释
Vaadin 也不支持在静态字段中存储组件。就我而言,这就是问题所在。 (Vaadin 18).