未授权用户的 Blazor 登录页面

Hil*_*lle 5 c# authentication routes blazor blazor-webassembly

目标:
如果用户未登录,我希望有一种登陆页面(基本上所有其他页面都应该被锁定,而不需要[Authorize]所有页面上的属性)。


设置:

  • Blazor WASM
  • ASP.NET托管(具有IdentityServer授权)

代码:
我已经重写了MainLayout.razor将所有未经授权的请求重定向到我的重定向处理程序

<NotAuthorized>
    <RedirectToLogin />
</NotAuthorized>
Run Code Online (Sandbox Code Playgroud)

我的RedirectToLogin.razor包含名为的登录页面Index.razorRemoteAuthenticatorView身份验证请求

@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@if (!string.IsNullOrEmpty(action))
{
    <RemoteAuthenticatorView Action="@action" />
}
else
{
    <div>
        Landing page...<br />
        <a href="/authentication/Login">Login</a><br />
        <a href="/authentication/Register">register</a>
    </div>
}
Run Code Online (Sandbox Code Playgroud)

我的RedirectToLogin.razor.cs确实侦听位置更改并将身份验证请求转发到RemoteAuthenticatorView

public partial class RedirectToLogin : IDisposable
{
    [CascadingParameter] private Task<AuthenticationState> AuthenticationStateTask { get; set; }

    [Inject] private NavigationManager NavigationManager { get; set; }

    string action = "";

    protected override async Task OnInitializedAsync()
    {
        NavigationManager.LocationChanged += LocationChanged;
    }

    public void Dispose()
    {
        NavigationManager.LocationChanged -= LocationChanged;
    }

    async void LocationChanged(object sender, LocationChangedEventArgs e)
    {
        action = "";

        var authenticationState = await AuthenticationStateTask;

        if (authenticationState?.User?.Identity is not null)
        {
            var url = Navigation.ToBaseRelativePath(Navigation.Uri);

            if (!authenticationState.User.Identity.IsAuthenticated)
            {
                if (url == "authentication/logged-out")
                {
                    NavigationManager.NavigateTo("", true);
                    return;
                }

                if (url.Contains("authentication"))
                {
                    var index = url.IndexOf("authentication") + 15;
                    if (url.Contains("?"))
                        action = url.Substring(index, url.IndexOf('?') - index);
                    else
                        action = url.Substring(index);
                }
                this.StateHasChanged();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:除了登录回调之外,
整个系统基本上可以很好地处理所有身份验证请求。

它仍然显示登陆页面,而不是加载授权视图。

您需要刷新页面或再次点击登录按钮才能重定向到授权视图。

我尝试在导航更改时使用 url 中的登录回调或在用户被授权时手动导航用户,但似乎没有任何效果。

您知道为什么会发生这种行为和/或如何解决此问题吗?


如果有更简单的方法来实现我的目标,请发表评论。我在网上没有找到任何东西并尽了最大努力。

Cor*_*jil 2

问题是您正在将与身份验证相关的所有内容传递到此登录页面。您需要有两个单独的页面来执行您想要执行的操作,一个用于未经授权的用户的登录页面,另一个用于授权用户的登录页面。

要更改此设置,您需要更新Program.cs文件并设置AuthenticationPathsunder builder.Services.AddApiAuthorization. 这是一个例子:

builder.Services.AddApiAuthorization(options =>
{
    options.AuthenticationPaths.LogInPath = "auth/login";
    options.AuthenticationPaths.LogInCallbackPath = "auth/login-callback";
    options.AuthenticationPaths.LogInFailedPath = "auth/login-failed";
    options.AuthenticationPaths.LogOutPath = "auth/logout";
    options.AuthenticationPaths.LogOutCallbackPath = "auth/logout-callback";
    options.AuthenticationPaths.LogOutFailedPath = "auth/logout-failed";
    options.AuthenticationPaths.LogOutSucceededPath = "auth/logged-out";
    options.AuthenticationPaths.ProfilePath = "auth/profile";
    options.AuthenticationPaths.RegisterPath = "auth/register";
    options.AuthenticationPaths.RemoteProfilePath = "/profile";
    options.AuthenticationPaths.RemoteRegisterPath = "/register";
});
Run Code Online (Sandbox Code Playgroud)

然后是Authentication.razor页面:

@page "/auth/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action">
    <LoggingIn></LoggingIn>
    <CompletingLoggingIn></CompletingLoggingIn>
    <LogInFailed>Failed to log in.</LogInFailed>
    <LogOut></LogOut>
    <LogOutFailed>Failed to log out.</LogOutFailed>
    <CompletingLogOut></CompletingLogOut>
    <LogOutSucceeded><RedirectToLogin ReturnUrl="Dashboard"/></LogOutSucceeded>
    <UserProfile></UserProfile>
    <Registering></Registering>
</RemoteAuthenticatorView>

@code{
    [Parameter] public string Action { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

有关 的更多信息RemoteAuthenticatorView,请查看此 Microsoft 文档:https://learn.microsoft.com/en-us/aspnet/core/blazor/security/web assembly/additional-scenarios?view=aspnetcore-5.0#customize-app-路线

就在该部分下方:https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassemble/additional-scenarios ?view=aspnetcore-5.0#customize-the-authentication-user-interface