Blazor 中某些不安全页面的身份验证/授权

问题描述 投票:0回答:1

我正在努力使 Blazor 中的身份验证/授权与一些公共页面(如登录、隐私政策、错误页面等)结合使用。经过多次修补后,它似乎有效,但我无法想象我所做的方式是推荐的方式。我正在使用 Auth0 进行身份验证——我不确定这是否重要(可能不重要)。

我正在将 Blazor 服务器 Web 应用程序与 .Net 8 结合使用,该应用程序是从 .Net 7 Blazor 服务器应用程序转换而来。

我不会发布整个 Routes.razor,但它引用了 MainLayout (我认为这是标准的):

<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">

MainLayout.razor 然后有一个带有几层身份验证的 AuthorizedView。 @Body 嵌套在 Authorized 部分内的 ErrorBoundary 中,第二个 @Body 标记位于 NotAuthorized 部分(下面仅是部分片段):

<AuthorizeView>
    <Authorized>
       [...]
            <ErrorBoundary @ref="_errorBoundary">
                <ChildContent>
                    @Body
                </ChildContent>
                <ErrorContent Context="ex">
                    @{
                        OnError(ex);
                    }
                    <p>Something has gone wrong. The error has been logged.</p>
                </ErrorContent>
            </ErrorBoundary>
       [...]
    </Authorized>
    <NotAuthorized>
       @Body
    </NotAuthorized>
</AuthorizeView>

背后的代码 (MainLayout.razor.cs) 在 Init 上执行以下操作:

private static readonly List<string> PublicUris = new() { "/privacy", "/login", "/error" };

protected override async Task OnInitializedAsync()
{
    var authenticationStateAsync = await AuthStateProvider.GetAuthenticationStateAsync();
    User = authenticationStateAsync.User;

    var baseUri = NavigationManager.BaseUri.TrimEnd('/');

    //TODO: is this how it needs to work?
    //Note: all public pages would have to be added to this page?
    var publicPage = PublicUris.Select(p => baseUri + p).Contains(NavigationManager.Uri);
    
    if (User.Identity is not { IsAuthenticated: true } && !publicPage)
    {
        NavigationManager.NavigateTo($"/{UnauthorizedRedirectUrl}");
    }

    await base.OnInitializedAsync();
}

这有点笨拙,但要点是如果当前页面不是公共页面并且用户未登录,则重定向到登录页面。

Program.cs 的一些内容。不确定有多少相关:

builder.Services
    .AddAuth0WebAppAuthentication(options => {[...]

//added based on: https://stackoverflow.com/questions/74555220/custom-loginpath-no-effect-in-asp-net-mvc-with-auth0
builder.Services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options => {
    options.LoginPath = "/";
    options.LogoutPath = "/Identity/Logout";
});
[...]
builder.Services.AddAuthorization(options =>
{[policies that I don't think are relevant]...
[...]
app.UseAuthentication();
app.UseAuthorization();

再次,这似乎可以工作,无论是否登录都可以看到公共页面,并且不需要需要AllowAnonymous属性才能看到。

也就是说,我还没有在任何地方找到一篇文章建议这样做,或者说任何有关检查主布局页面后面的代码中的当前 Uri 和重定向的内容。

如何在 Blazor 应用程序中同时支持安全页面和公共页面,而无需进行类似上述的设计?

c# asp.net-core authentication blazor auth0
1个回答
0
投票

您可以将

@attribute [Authorize]
添加到
_Imports.razor
以使授权全局化。然后将
@attribute [AllowAnonymous]
添加到公共页面。
如果您想使用公共页面 Uris 列表,您可以保留
@attribute [Authorize]
,然后添加自定义授权处理程序以根据请求 Uri 确定身份验证结果。
MyAuthHandler.cs

    public class MyAuthHandler : IAuthorizationHandler
    {
        private readonly IHttpContextAccessor accessor;

        private static readonly List<string> PublicUris = new() { "/counter", "/login", "/error" };
        public MyAuthHandler(IHttpContextAccessor accessor)
        {
            this.accessor = accessor;
        }

        public Task HandleAsync(AuthorizationHandlerContext context)
        {

            var currentUri = accessor.HttpContext.Request.Path;

            var pendingRequirements = context.PendingRequirements.ToList();

            foreach (var requirement in pendingRequirements)
            {
                if (PublicUris.Contains(currentUri))
                {
                    context.Succeed(requirement);
                }
            }
            return Task.CompletedTask;
        }
    }

然后在程序.cs中

builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<IAuthorizationHandler, MyAuthHandler>();
builder.Services.AddAuthorization(...);

请注意,所有注册的“IAuthorizationHandler”都将由默认授权服务进行处理。 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-8.0#iauthorizationservice

© www.soinside.com 2019 - 2024. All rights reserved.