如何在Blazor WebAssembly中绕过部分页面的身份验证检查?
Blazor WebAssembly 配置部分页面匿名访问(.NET 7 + Identity Server)
问题描述
我正在使用.NET 7 Blazor WebAssembly搭配.NET Core托管服务器项目,采用Identity Server进行身份认证与授权。希望部分页面可匿名访问,但未找到合适的客户端项目配置方式以跳过这些页面的身份验证检查,该如何实现?
当前客户端Program.cs代码:
using DotnetExpert.BlazorPWA.Client; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddHttpClient("DotnetExpert.BlazorPWA.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("DotnetExpert.BlazorPWA.ServerAPI")); builder.Services.AddApiAuthorization(); await builder.Build().RunAsync();
当前App.razor代码:
<CascadingAuthenticationState> <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> @if (context.User.Identity?.IsAuthenticated != true) { <RedirectToLogin /> } else { <p role="alert">You are not authorized to access this resource.</p> } </NotAuthorized> </AuthorizeRouteView> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
实现步骤
1. 为目标页面标记匿名访问权限
在需要允许匿名访问的页面组件顶部添加[AllowAnonymous]特性,直接告知授权系统跳过该页面的验证:
@page "/" @attribute [AllowAnonymous] <h1>欢迎访问首页(匿名可进)</h1>
2. 调整App.razor的路由授权逻辑
当前AuthorizeRouteView会默认对所有路由强制验证,需要修改为仅对**未标记[AllowAnonymous]**的页面执行授权检查:
修改后的App.razor代码:
<CascadingAuthenticationState> <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> @{ // 检测当前页面是否包含匿名访问特性 var isAnonymousPage = routeData.PageType .GetCustomAttributes(typeof(Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute), inherit: true) .Any(); } @if (isAnonymousPage) { // 匿名页面直接渲染,不经过授权拦截 <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> } else { // 需授权页面保留原有验证逻辑 <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> @if (context.User.Identity?.IsAuthenticated != true) { <RedirectToLogin /> } else { <p role="alert">你无权访问此资源。</p> } </NotAuthorized> </AuthorizeRouteView> } <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>未找到页面</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">抱歉,该地址不存在任何内容。</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
3. 配置匿名API访问的HttpClient(可选)
如果匿名页面需要调用无需授权的后端API,需创建一个不带授权消息处理器的HttpClient:
修改Program.cs代码,新增匿名HttpClient实例:
using DotnetExpert.BlazorPWA.Client; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); // 带授权的HttpClient:用于需认证的API调用 builder.Services.AddHttpClient("DotnetExpert.BlazorPWA.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); // 匿名HttpClient:用于无需认证的API调用 builder.Services.AddHttpClient("DotnetExpert.BlazorPWA.AnonymousAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)); // 注册两种HttpClient实例 builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("DotnetExpert.BlazorPWA.ServerAPI")); builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("DotnetExpert.BlazorPWA.AnonymousAPI")); builder.Services.AddApiAuthorization(); await builder.Build().RunAsync();
在匿名页面中使用该HttpClient:
@inject HttpClient AnonymousHttpClient @code { protected override async Task OnInitializedAsync() { var anonymousData = await AnonymousHttpClient.GetFromJsonAsync<object>("api/anonymous/get-data"); } }
4. 后端API同步配置(补充)
确保后端对应API端点也添加[AllowAnonymous]特性,否则客户端允许匿名后,后端仍会拒绝访问:
[ApiController] [Route("api/anonymous")] public class AnonymousApiController : ControllerBase { [HttpGet("get-data")] [AllowAnonymous] public IActionResult GetAnonymousData() { return Ok(new { Content = "这是匿名可访问的API数据" }); } }
内容的提问来源于stack exchange,提问作者Robin Khan
相关产品推荐
相关产品推荐

