目标:
如果用户没有登录,我希望有一种登录页面(基本上所有其他页面都应该被锁定,而不需要所有页面上的[Authorize]
属性)。
设置:
- Blazor WASM
- ASP。NET托管(具有Identity Server授权)
代码:
我已经重写了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中使用登录回调或用户获得授权时手动导航用户,但似乎什么都不起作用。
你知道为什么会发生这种行为和/或如何解决这种情况吗?
请评论是否有更简单的方法来实现我的目标。我没有在网上找到任何东西,我尽力了
问题是您正在将与身份验证相关的所有内容传递到此登录页。你需要有两个单独的页面来处理你想要做的事情,一个是未授权用户的登录页面,另一个是授权用户的登陆页面。
要更改此设置,您需要更新Program.cs
文件,并在builder.Services.AddApiAuthorization
下设置AuthenticationPaths
。这里有一个例子:
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://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-5.0#自定义应用程序路由
就在该部分下方:https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-5.0#自定义身份验证用户界面