I have trouble migrating from Vaadin 14 to Vaadin 23. I have a long running backgroundtask with a progress dialog. With Vaadin 14 after finishing the task i could navigate to a result-view with the following code:
UI ui = UI.getCurrent();
final SecurityContext context = SecurityContextHolder.getContext();
ui.access(() -> {
SecurityContextHolder.setContext(context);
UI.navigate("work-finished-view");
});
With Vaadin 23 i get this warning
(ViewAccessChecker.java:147) Preventing navigation to com.vaadin.flow.router.RouteNotFoundError because no HTTP request is available for checking access.
This is the code in com.vaadin.flow.server.auth.ViewAccessChecker
VaadinServletRequest vaadinServletRequest = VaadinServletRequest.getCurrent();
if (vaadinServletRequest == null) {
// This is in a background thread and we cannot access the request
// to check access
getLogger().warn("Preventing navigation to " targetView.getName()
" because no HTTP request is available for checking access.");
beforeEnterEvent.rerouteToError(NotFoundException.class);
return;
}
What is the right way to navigate to another view from a background thread?
CodePudding user response:
You would need create a fake request that uses the values from the security context holder and set that request using CurrentInstance.set(VaadinRequest.class, request);
. Completely doable but not very nice.
Instead of writing a long and hacky example here for how it could be done, I spent the time on creating a pull request to make this work out of the box in the future: https://github.com/vaadin/flow/pull/13675
CodePudding user response:
If you are using the VaadinWebSecurityConfigurerAdapter
the SecurityContext
should automatically be available in the UI thread. Unfortunately, the ViewAccessChecker
will not make use of it either way. The way it's implemented (i.e. in a Spring independent way) it simply requires a HttpServletRequest
. So I currently don't see a right way to do this (with vanilla Vaadin, anyway). You should probably create a ticket on Github because this seems like a pretty important use case.
Maybe you could redirect to an unprotected view that requires the user to click a button to navigate to the protected one. Page#setLocation(...) would also create a new request for the security check, but that will not navigate within Vaadin and basically recreate your UI. But both options are pretty far down on the list of acceptable workarounds, honestly.
If no one else can provide an actually reasonable workaround, you could check out my add-on: Spring Boot Security for Vaadin. It does use Spring's SecurityContext
so it would work in your case.