如何获取用户是不是登录的最新信息?

Posted

技术标签:

【中文标题】如何获取用户是不是登录的最新信息?【英文标题】:How to get fresh information whether the user is logged in?如何获取用户是否登录的最新信息? 【发布时间】:2021-04-24 14:19:58 【问题描述】:

在这种特殊情况下,我只对获取用户是否登录的信息感兴趣。

按照How to enable/disable elements depending whether the user is logged in or not? 的答案,我可以获取此信息,但有一个奇怪的问题。

我使用 Blazor 演示应用程序,它在顶部显示提供的“LoginDisplay.razor”组件,我自己的页面使用以下代码:

@code 
  protected override async Task OnInitializedAsync()
  
      Console.WriteLine("Init");

      var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
      var authenticated = authState.User.Identity?.IsAuthenticated ?? false;

      Console.WriteLine($"We are authenticated");
  

我在使用这个应用时分三个步骤:

    我启动了应用程序,但我没有登录,“LoginDisplay”显示“登录”提示并且我的代码打印我没有通过身份验证——很好

    我点击“登录”,我登录,我被重定向回我的页面——“LoginDisplay”现在显示我的名字,但我的代码仍然打印我没有经过身份验证(使用“NavMenu”时会发生这种错误的打印输出.razor”,但在使用“Index.razor”时很好 - 请参阅下面的更新)

    我按 F5(重新加载页面)——“LoginDisplay”显示我的名字,并且代码打印出我已通过身份验证——正如预期的那样

所以步骤(2)是有问题的——我应该得到我登录的信息(因为我是),显然“LoginDisplay”能够实现这一事实。那么我应该在我的代码中添加什么逻辑以显示我已登录?

更新在@enet 回复之后,我意识到步骤 (2) 的结果取决于您将此代码放在哪里——如果它在登录打印输出后立即放置在“NavMenu.razor”中,说明您未经授权。当我将相同的代码放入“Index.razor”(主页)时,打印输出正确地表明我已登录。

我可以看到渲染“NavMenu”几乎是立即的,而“Index”是在暂停后渲染的。所以问题更多的是“无论使用页面,如何获取新的身份验证信息?”。

【问题讨论】:

你能分享一下你是如何更新authentication state provider的吗? @SuprabhatBiswal,我不确定您要什么,提供的 sn-p 是我使用的整个代码。但是看到更新,我在哪里使用这个代码更相关。 【参考方案1】:

以下代码描述了如何在 MainLayout 组件中显示消息:

<LoginDisplay />
<div>IsAuthenticated: @authenticated.ToString()</div>


@code 

bool authenticated;

[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask get; set;

protected override async Task OnInitializedAsync()

    Console.WriteLine("Init");

    var authState = await authenticationStateTask;
    var user = authState.User;


    authenticated = user.Identity?.IsAuthenticated ?? false;
    Console.WriteLine($"We are authenticated");

注意上面的代码只有在MainLayout组件初始化的时候才会执行。为了刷新已验证消息的显示, 我们需要再次执行代码。这可以通过执行以下操作来实现:

在 Authentication 组件中,向 RemoteAuthenticatorView 组件实例添加用户登录后调用的事件处理程序属性OnLogInSucceeded,如下所示:

<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded="RefreshMain" />

添加事件处理程序RefreshMain

 private void RefreshMain()
    
        NavigationManager.NavigateTo("mainlayout");
    

事件处理程序代码只是重定向到 MainLayout

为 NavigationManager 添加 @inject 指令,如下所示:

@inject NavigationManager NavigationManager;

请注意,您可以像这样简单地使用 AuthorizeView 组件来代替上面的代码:

<LoginDisplay />

<div>
<AuthorizeView>
    <Authorized>
        <div>@context.User.Identity.IsAuthenticated</div>
    </Authorized>
    <NotAuthorized>
        <div>@context.User.Identity.IsAuthenticated</div>
    </NotAuthorized>
</AuthorizeView>
</div>

更新

您通常不直接使用 AuthenticationStateProvider。使用本文后面介绍的 AuthorizeView 组件或任务方法。直接使用 AuthenticationStateProvider 的主要缺点是,如果底层身份验证状态数据发生更改,则不会自动通知组件。 Source...

不要为渲染而烦恼。通常,除非您的代码无休止地重新渲染,否则没有问题。

无论如何,以下代码示例描述了您应该如何真正做到这一点:

将 Authentication 组件中的代码反转为默认状态

将您在 MainLayout 中添加的代码更改为以下内容

 @inherits LayoutComponentBase

 @inject AuthenticationStateProvider AuthenticationStateProvider

 <div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <div class="main">
        <div class="top-row px-4 auth">
            <LoginDisplay />
            <div>IsAuthenticated: @authenticated.ToString()</div>
            <a href="https://docs.microsoft.com/aspnet/" 
                                        target="_blank">About</a>
        </div>
        <div class="content px-4">
            @Body
        </div>
     </div>
  </div>

  @code 

    private bool authenticated;

    protected override void OnInitialized()
    
        Task<AuthenticationState> _currentAuthenticationStateTask;

        AuthenticationStateProvider.AuthenticationStateChanged += 
                                       OnAuthenticationStateChanged;

        _currentAuthenticationStateTask = 
          AuthenticationStateProvider.GetAuthenticationStateAsync();

        OnAuthenticationStateChanged(_currentAuthenticationStateTask);
    

    private void OnAuthenticationStateChanged
                  (Task<AuthenticationState> authenticationStateTask)
    
        _ = InvokeAsync(async () =>
        
            var authState = await authenticationStateTask;
            var user = authState.User;


            authenticated = user.Identity?.IsAuthenticated ?? false;
            StateHasChanged();
        );
    

  

【讨论】:

谢谢,它有效,但无效:-) 我测试了它,它似乎很大程度上取决于你添加它的位置——当我将它添加到“NavMenu.razor”时(这是我想要它的地方)它的行为就像我原来的帖子一样,但是当我把它放到“Index.razor”(主页)时它工作正常。从打印输出的时间来看,似乎“NavMenu”的渲染时间要快得多,并且还没有身份验证信息。 非常感谢,我需要第一种方法,因为我想在代码中获取变量,说明用户是否经过身份验证。一件奇怪的事情是,在不改变 RemoteAuthenticatorView 的情况下,NavMenu 被渲染了一次。现在它被渲染了三次——第一次显示用户没有登录(错误),第二次是,第三次是。我想知道为什么它在第一遍时没有新数据。 我添加了一个新的更新。如果您需要澄清,请随时提出。 这很棒,单次渲染,我现在什至了解了工作流程:-)。非常感谢! 它可以工作,但只是没有在 OnInitialized 中达到我的断点,所以我有点困惑

以上是关于如何获取用户是不是登录的最新信息?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取其他系统登录的用户信息

如何在 Hive 查询中使用 row_number 来获取最新的用户登录?

如何获取与已登录用户相关的信息?

如何获取登录用户 SpringSecurity + AngularJS 的用户信息

如何在 Django 应用程序中获取有关登录用户的信息?

如何使用 JWT 身份验证获取登录用户信息?