我想为Blazor中的身份验证错误指定一个非默认布局



我想在下面的错误中指定布局。

  • 未找到路由
  • 未经授权
  • 禁止

文件详细信息

App.razor

<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<!-- TODO RZ9999 when Context removed -->
<AuthorizeView Context="authenticated">
<Authorized>
<!-- TODO ErrorLayout -->
<Error403/>
</Authorized>
<NotAuthorized>
<!-- TODO ErrorLayout -->
<Error401/>
</NotAuthorized>
</AuthorizeView>
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

Error401.razor、Error403.razor和Error404.razor

<PageTitle>Error401</PageTitle>
<h3>Error401</h3>
<PageTitle>Error403</PageTitle>
<h3>Error403</h3>
<PageTitle>Error404</PageTitle>
<h3>Error404</h3>

我尝试过的

根据文件详细信息中的描述,ErrorLayout用于Error404,但MainLayout应用于Error401和Error403。
我尝试了以下描述,但不起作用。

添加@布局

Error401.razor如下,但应用了MainLayoute。@layout只对那些有@page的人有效吗?

@layout ErrorLayout
<PageTitle>Error401</PageTitle>
<h3>Error401</h3>

添加布局视图

如果Error401和Error403是LayoutView的子级,它们将嵌套在MainLayout和ErrorLayout布局中。

<AuthorizeView Context="authenticated">
<Authorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error403/>
</LayoutView>
</Authorized>
<NotAuthorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error401/>
</LayoutView>
</NotAuthorized>
</AuthorizeView>

问题

在授权和身份验证错误的情况下,我如何编写路由器来指定布局?

@layout是否只对带有@page的用户有效?

是的。。。也可以将其添加到布局中以指定嵌套。

仅供参考:401和403都被<NotAuthorized>捕获。

使用类似的组件

public class RedirectToPage : ComponentBase
{
[Inject]
private NavigationManager Navigation { get; set; }
[Parameter]
public string Href { get; set; }
protected override void OnInitialized()
=> Navigation.NavigateTo(Href);
}

您可以将其扩展为包括返回地址等

App.razor内部

<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated == true)
{
<RedirectToPage Href="/error403" />
}
else
{
<RedirectToPage Href="/error401" />
}
</NotAuthorized>

使用您选择的@layout ...创建适当的错误页面。

我通过创建AuthorizeRouteView的自定义版本解决了这个问题
基于Blazor源AuthorizeRouteView创建具有以下更改的CustomAuthorizeRouteView。

public sealed class CustomAuthorizeRouteView : RouteView
{
...
[Parameter]
public Type NotAuthorizedLayout { get; set; }
...
private void RenderContentInNotAuthorizedLayout(RenderTreeBuilder builder, RenderFragment content)
{
builder.OpenComponent<LayoutView>(0);
builder.AddAttribute(1, nameof(LayoutView.Layout), NotAuthorizedLayout);
builder.AddAttribute(2, nameof(LayoutView.ChildContent), content);
builder.CloseComponent();
}
private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState)
{
var content = NotAuthorized ?? _defaultNotAuthorizedContent;
RenderContentInNotAuthorizedLayout(builder, content(authenticationState));
}
...
}

App.razor

<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<CustomAuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" NotAuthorizedLayout="@typeof(ErrorLayout)">
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
<Error401/>
}
else
{
<Error403/>
}
</NotAuthorized>
</CustomAuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

有了这些内容,我可以在不使用原始URL导航的情况下做我想做的事情。

完整来源

  • GitHub

一种更简单的方法是在MainLayout.razor文件中设置适当的布局。像这个

@inherits LayoutComponentBase
<!-- Page wrapper -->
<AuthorizeView>
<Authorized>
<div class="flex flex-row h-screen bg-slate-50 overflow-hidden">
<!-- Side Bar-->
<SideBar/>
<!-- Content area -->
<div class="">
<!-- site header -->
<HeaderLayout/>
<main>
<div class="px-4 sm:px-6 lg:px-8 py-8 bg-slate-50">
@Body
</div>
</main>
</div>
</div>
</Authorized>
<NotAuthorized>
@Body
</NotAuthorized>
<Authorizing>
<p>Hold up, lemma check you out.</p>
</Authorizing>
</AuthorizeView>

最新更新