首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SecurityContext.getAuthentication()在Vaadin导航后返回null

SecurityContext.getAuthentication()在Vaadin导航后返回null
EN

Stack Overflow用户
提问于 2022-03-27 20:05:39
回答 1查看 1.1K关注 0票数 0

在我的论文中,我正在用Vaadin和Spring做一个订单管理web应用程序。

代码语言:javascript
复制
@Slf4j
@Route("app/end-user/sent")
public class SentToRestaurantView extends EndUserViewBase {
    Registration broadcasterRegistration;

    public SentToRestaurantView() {
        super("Sent to restaurant");

        add(
                new H1("Your order has been sent"),
                new H2("The restaurant has received your order. They will respond with a time estimate in a few minutes.")
        );
    }


    private void onUpdate(String message) {
        // here is the redirect
        UI.getCurrent().navigate(InTheMakingView.class);
        log.info(message);
    }

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        UI ui = attachEvent.getUI();
        broadcasterRegistration = Broadcaster.register(newMessage -> ui.access(() -> onUpdate(newMessage)));
    }

    @Override
    protected void onDetach(DetachEvent detachEvent) {
        broadcasterRegistration.remove();
        broadcasterRegistration = null;
    }
}

用户在将订单发送到餐厅后将获得此视图。如果餐厅接受它(并广播消息),我希望将用户重定向到另一个视图;您可以在SentToRestaurantView::onUpdate中看到这一点。问题是,在重定向过程中,会发生错误。

代码语言:javascript
复制
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.example.demo.ui.enduser.view.InTheMakingView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.ui.enduser.view.InTheMakingView]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:315) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:296) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:332) ~[spring-beans-5.3.12.jar:5.3.12]
        at com.vaadin.flow.spring.SpringInstantiator.getOrCreate(SpringInstantiator.java:117) ~[vaadin-spring-18.0.0.jar:na]
        at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:193) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:135) ~[flow-server-8.0.4.jar:8.0.4]
        at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na]
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:134) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.sendBeforeEnterEventAndPopulateChain(AbstractNavigationStateRenderer.java:488) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.createChainIfEmptyAndExecuteBeforeEnterNavigation(AbstractNavigationStateRenderer.java:469) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:207) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.internal.JavaScriptNavigationStateRenderer.handle(JavaScriptNavigationStateRenderer.java:79) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.internal.JavaScriptBootstrapUI.handleNavigation(JavaScriptBootstrapUI.java:315) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.internal.JavaScriptBootstrapUI.navigate(JavaScriptBootstrapUI.java:223) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.navigate(UI.java:917) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.navigate(UI.java:898) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.navigate(UI.java:834) ~[flow-server-8.0.4.jar:8.0.4]
        at com.example.demo.ui.enduser.view.SentToRestaurantView.onUpdate(SentToRestaurantView.java:31) ~[classes/:na]
        at com.example.demo.ui.enduser.view.SentToRestaurantView.lambda$onAttach$b3eb7f9f$1(SentToRestaurantView.java:38) ~[classes/:na]
        at com.vaadin.flow.component.UI.accessSynchronously(UI.java:446) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.access$000(UI.java:97) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI$2.execute(UI.java:521) ~[flow-server-8.0.4.jar:8.0.4]
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
        at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2039) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.server.VaadinSession.unlock(VaadinSession.java:720) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:2005) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.server.VaadinService.accessSession(VaadinService.java:1972) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.server.VaadinSession.access(VaadinSession.java:1023) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.access(UI.java:518) ~[flow-server-8.0.4.jar:8.0.4]
        at com.vaadin.flow.component.UI.access(UI.java:501) ~[flow-server-8.0.4.jar:8.0.4]
        at com.example.demo.ui.enduser.view.SentToRestaurantView.lambda$onAttach$0(SentToRestaurantView.java:38) ~[classes/:na]
        at com.example.demo.backend.broadcast.Broadcaster.lambda$broadcast$0(Broadcaster.java:26) ~[classes/:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
        at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.ui.enduser.view.InTheMakingView]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:224) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117) ~[spring-beans-5.3.12.jar:5.3.12]
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:311) ~[spring-beans-5.3.12.jar:5.3.12]
        ... 39 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
        at com.example.demo.security.user.enduser.service.details.EndUserDetailsServiceImpl.getUser(EndUserDetailsServiceImpl.java:19) ~[classes/:na]
        at com.example.demo.ui.enduser.view.EndUserViewBase.<init>(EndUserViewBase.java:21) ~[classes/:na]
        at com.example.demo.ui.enduser.view.InTheMakingView.<init>(InTheMakingView.java:18) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[na:na]
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) ~[na:na]
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211) ~[spring-beans-5.3.12.jar:5.3.12]
        ... 41 common frames omitted
代码语言:javascript
复制
@Route("app/end-user/waiting")
@Slf4j
public class InTheMakingView extends EndUserViewBase {
    @Autowired
    public InTheMakingView(EndUserDetailsService endUserDetailsService) {
        super("In the making");

        var order = endUserDetailsService.getUser().getTable().getOrderSession().getLastOrder();

        add(
                new H1("Your order is in the making"),
                new H2(String.format("In about %d minutes our college, %s, will serve you your meal", order.getEstimatedTimeOfDoingInMinutes(), order.getServer().getName()))
        );
    }
}
代码语言:javascript
复制
@Slf4j
public abstract class EndUserViewBase extends ViewBase {
    protected EndUserViewBase(String title) {
        super(title);

        var detailsService = BeanUtil.getBean(EndUserDetailsService.class);

        add(
                new Header(String.format(
                        "%s | %s",
                        detailsService.getUser().getTable().getRestaurant().getName(),
                        title))
        );
    }
}

显然,在EndUserDetaulsService方法中对EndUserDetaulsService的调用在EndUserViewBase的构造函数中返回null。刷新页面后,它将按预期工作。

代码语言:javascript
复制
@Service
@Slf4j
public class EndUserDetailsServiceImpl implements EndUserDetailsService{
    @Autowired
    EndUserService endUserService;

    @Override
    public EndUser getUser() {
        var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        String userId = "";

        // TOPIC pattern matching
        if (principal instanceof UserDetails userDetails) {
            userId = userDetails.getUsername();
        }

        var user =
                endUserService.getUser(userId);

        if (user.isEmpty()) {
            throw new RuntimeException(String.format("User with email %s was not found", userId));
        } else {
            return user.get();
        }

    }
}

我无法找出此错误的来源,以及它如何与导航相关,或者为什么不显化,如果我重新加载页面,这是以前崩溃的。

EN

回答 1

Stack Overflow用户

发布于 2022-03-28 07:40:11

您的EndUserDetailsServiceImpl是单例服务,因此SecurityContextHolder是不可用的。您需要重构您的代码,以便在服务中不使用SecurityContextHolder。您需要将userId作为参数传递。

代码语言:javascript
复制
public EndUser getUser(String userId) {
    // TOPIC pattern matching
    if (principal instanceof UserDetails userDetails) {
        userId = userDetails.getUsername();
    }

    var user =
            endUserService.getUser(userId);

    if (user.isEmpty()) {
        throw new RuntimeException(String.format("User with email %s was not found", userId));
    } else {
        return user.get();
    }

}

即从主体获取userId,然后调用该方法。

代码语言:javascript
复制
public InTheMakingView(EndUserDetailsService endUserDetailsService) {
    super("In the making");

    var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

    String userId = "";

    // TOPIC pattern matching
    if (principal instanceof UserDetails userDetails) {
        userId = userDetails.getUsername();
    }

    var order = endUserDetailsService.getUser(userId).getTable().getOrderSession().getLastOrder();

    add(
            new H1("Your order is in the making"),
            new H2(String.format("In about %d minutes our college, %s, will serve you your meal", order.getEstimatedTimeOfDoingInMinutes(), order.getServer().getName()))
    );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71639894

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档