未授权用户的 Blazor 登录页面

时间:2021-03-07 22:15:41

标签: c# authentication routes blazor blazor-webassembly

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


设置:

  • Blazor WASM
  • ASP.NET 托管(使用 IdentityServer 授权)

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

<NotAuthorized>
    <RedirectToLogin />
</NotAuthorized>

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

@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>
}

我的 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();
            }
        }
    }
}

问题:
整个系统基本上适用于所有身份验证请求,登录回调除外

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

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

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

您知道为什么会出现这种行为和/或如何解决这个问题吗?


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

1 个答案:

答案 0 :(得分:1)

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

要更改此设置,您需要更新 Program.cs 文件并在 AuthenticationPaths 下设置 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";
});

然后是 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; }
}

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

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