C# 非授权用户的Blazor登录页

C# 非授权用户的Blazor登录页,c#,authentication,routes,blazor,blazor-webassembly,C#,Authentication,Routes,Blazor,Blazor Webassembly,目标: 如果用户未登录,我希望有一种登录页面(基本上所有其他页面都应锁定,而无需在所有页面上使用[Authorize]属性) 设置: 布拉佐·瓦斯姆 ASP.NET托管(具有IdentityServer授权) 代码: 我已经重写了MainLayout.razor,将所有未授权的请求重定向到我的重定向处理程序 <NotAuthorized> <RedirectToLogin /> </NotAuthorized> MyRedirectToLog

目标:
如果用户未登录,我希望有一种登录页面(基本上所有其他页面都应锁定,而无需在所有页面上使用
[Authorize]
属性)


设置:

  • 布拉佐·瓦斯姆
  • ASP.NET托管(具有IdentityServer授权)

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

<NotAuthorized>
    <RedirectToLogin />
</NotAuthorized>
My
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();
            }
        }
    }
}
public部分类重定向到登录:IDisposable
{
[CascadingParameter]专用任务AuthenticationStateTask{get;set;}
[注入]专用导航管理器导航管理器{get;set;}
字符串动作=”;
受保护的重写异步任务OnInitializedAsync()
{
NavigationManager.LocationChanged+=LocationChanged;
}
公共空间处置()
{
NavigationManager.LocationChanged-=LocationChanged;
}
异步void LocationChanged(对象发送方,LocationChangedEventArgs e)
{
action=“”;
var authenticationState=等待AuthenticationStateTask;
if(authenticationState?.User?.Identity不为空)
{
var url=Navigation.ToBaseRelativePath(Navigation.Uri);
如果(!authenticationState.User.Identity.IsAuthenticated)
{
如果(url==“身份验证/注销”)
{
NavigationManager.NavigateTo(“,true);
返回;
}
if(url.Contains(“身份验证”))
{
var index=url.IndexOf(“身份验证”)+15;
if(url.Contains(“?”)
action=url.Substring(index,url.IndexOf(“?”)-index);
其他的
action=url.Substring(索引);
}
此.StateHasChanged();
}
}
}
}

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

它不再加载授权视图,而是显示登录页。

您需要刷新页面或再次单击登录按钮以重定向到授权视图

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

你知道为什么会发生这种行为和/或如何解决吗



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

问题是您正在将与身份验证相关的所有信息传递到此登录页。你需要有两个独立的页面来完成你的任务,一个是未授权用户的登录页面,另一个是授权用户的登录页面

要更改此设置,您需要更新
Program.cs
文件,并在
builder.Services.addapiaauthorization
下设置
authenticationpath
。下面是一个例子:

builder.Services.AddApiAuthorization(选项=>
{
options.authenticationpath.LogInPath=“auth/login”;
options.authenticationpath.LogInCallbackPath=“auth/login回调”;
options.authenticationpath.LogInFailedPath=“auth/login失败”;
options.authenticationpath.LogOutPath=“auth/logout”;
options.authenticationpath.LogOutCallbackPath=“auth/logout callback”;
options.authenticationpath.LogOutFailedPath=“auth/logout失败”;
options.authenticationpath.LogOutSucceededPath=“auth/logged-out”;
options.authenticationpath.ProfilePath=“auth/profile”;
options.authenticationpath.RegisterPath=“auth/register”;
options.authenticationPath.RemoteProfilePath=“/profile”;
options.AuthenticationPath.RemoteRegisterPath=“/register”;
});
然后进入
Authentication.razor
页面:

@page”/auth/{action}
@使用Microsoft.AspNetCore.Components.WebAssembly.Authentication
登录失败。
无法注销。
@代码{
[参数]公共字符串操作{get;set;}
}
有关
RemoteAuthenticatorView
的更多信息,请查看以下Microsoft文档:


在该部分下方:

成功登录后,您是否从
Login.razor
更改了导航?如果您不知道,由于登录位置保持不变,给定的
LocationChanged
回调不应工作。我认为,这就是为什么你需要重新点击登录按钮或刷新页面。
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();
            }
        }
    }
}