gre*_*man 4 authentication blazor blazor-webassembly
在这种特殊情况下,我只对获取用户是否登录的信息感兴趣。
按照答案如何根据用户是否登录来启用/禁用元素?我可以获取此信息,但有一个奇怪的问题。
我使用 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}");
}
}
Run Code Online (Sandbox Code Playgroud)
我使用这个应用程序时分为三个步骤:
我启动应用程序,我没有登录,“LoginDisplay”显示“登录”提示,我的代码打印我没有经过身份验证 - 很好
我点击“登录”,登录,我被重定向回我的页面 - “LoginDisplay”现在显示我的名字,但我的代码仍然打印我没有经过身份验证(使用“NavMenu.razor”时会发生这种不正确的打印输出)但使用“Index.razor”时没问题——请参阅下面的更新)
我按 F5(重新加载页面)——“LoginDisplay”显示我的名字,代码打印出我已通过身份验证——正如预期的那样
所以步骤(2)是有问题的——我应该获取我登录的信息(因为我就是),显然“LoginDisplay”能够实现这个事实。那么我应该在代码中添加什么逻辑才能显示我已登录?
更新@enet 回复后,我意识到步骤 (2) 的结果取决于您放置此代码的位置 - 如果在登录打印输出后立即将其放置在“NavMenu.razor”中,则表明您未获得授权。当我将相同的代码放入“Index.razor”(主页)时,打印输出正确地表明我已登录。
我可以看到渲染“NavMenu”几乎是立即的,而“Index”是在暂停一段时间后渲染的。所以问题更多是“无论使用页面如何获取新的身份验证信息?”。
以下代码描述了如何在 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}");
}
Run Code Online (Sandbox Code Playgroud)
}
注意,上面的代码仅在MainLayout组件初始化时执行。为了刷新已验证消息的显示,我们需要再次执行代码。这可以通过执行以下操作来实现:
在 Authentication 组件中,将OnLogInSucceeded用户登录后调用的事件处理程序属性添加到 RemoteAuthenticatorView 组件实例,如下所示:
<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded="RefreshMain" />
Run Code Online (Sandbox Code Playgroud)
添加事件处理程序RefreshMain
private void RefreshMain()
{
NavigationManager.NavigateTo("mainlayout");
}
Run Code Online (Sandbox Code Playgroud)
事件处理程序代码只需重定向到 MainLayout
为 NavigationManager 添加 @inject 指令,如下所示:
@inject NavigationManager NavigationManager;
Run Code Online (Sandbox Code Playgroud)
请注意,您可以简单地使用 AuthorizeView 组件,如下所示:
<LoginDisplay />
<div>
<AuthorizeView>
<Authorized>
<div>@context.User.Identity.IsAuthenticated</div>
</Authorized>
<NotAuthorized>
<div>@context.User.Identity.IsAuthenticated</div>
</NotAuthorized>
</AuthorizeView>
</div>
Run Code Online (Sandbox Code Playgroud)
您通常不直接使用 AuthenticationStateProvider。使用本文后面描述的 AuthorizeView 组件或任务方法。直接使用 AuthenticationStateProvider 的主要缺点是,如果底层身份验证状态数据发生更改,则不会自动通知组件。 来源...
不要为渲染操心太多。通常,除非您的代码无休止地重新渲染,否则不会有任何问题。
无论如何,以下代码示例描述了您应该如何真正做到这一点:
将 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://learn.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();
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3756 次 |
| 最近记录: |