Blazor Server部署Azure后,如何调用带[Authorize]的API?
问题背景与需求
我使用Visual Studio的Blazor Web App模板(认证类型为Individual Accounts)创建了Blazor Server应用,添加了供用户下载文件的API,所有业务内容均需安全保护。
本地运行时代码正常,但部署到Azure App Service后,HttpContextAccessor.HttpContext始终为空,无法获取Cookie完成API认证。核心需求是:
- 不改动现有Blazor Server用户认证架构(当前运行稳定)
- 继续使用与应用其他部分一致的
[Authorize(Policy = "Admins")]特性保护API - 以简易方式解决Azure部署后的认证问题,仅需基础安全防护(数据不高度敏感,API无更新操作)
API控制器代码
[Authorize(Policy = "Admins")] [Microsoft.AspNetCore.Mvc.Route("api/[controller]")] [ApiController] public class DataDownloadController : ControllerBase {.....
Blazor端调用API的代码
var request = new HttpRequestMessage(HttpMethod.Get, fullUrl); var cookies = HttpContextAccessor.HttpContext.Request.Cookies; foreach (var cookie in cookies) request.Headers.Add("Cookie", $"{cookie.Key}={cookie.Value}"); var response = await Http.SendAsync(request); if (response.IsSuccessStatusCode) {.....
Program.cs配置代码
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped<ErrorHandler>(); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddCascadingAuthenticationState(); // 不加也能运行,但属于默认模板内容 builder.Services.AddScoped<IdentityUserAccessor>(); builder.Services.AddScoped<IdentityRedirectManager>(); builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>(); // 为了获取用户对象添加的配置 builder.Services.AddServerSideBlazor(); // 不确定是否需要,Gemini建议添加 //builder.Services.AddScoped<AuthenticationStateProvider, DefaultAuthenticationStateProvider>(); builder.Services.AddAuthorizationCore(); builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(); builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddSignInManager() .AddDefaultTokenProviders(); builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>(); builder.Services.AddAuthorization(options => { options.AddPolicy("LatzAdminPolicy", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == "IsLatzAdmin" && c.Value == "True"))); }); // 逻辑层的用户工具服务 builder.Services.AddScoped<IUserService, UserService>(); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContextFactory<ApplicationDbContext>(options => { options.UseSqlServer(connectionString, sqlOptionsBuilder => sqlOptionsBuilder.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(15), errorNumbersToAdd: null)); }); builder.Services.AddQuickGridEntityFrameworkAdapter(); builder.Services.AddApplicationInsightsTelemetry(options => { options.ConnectionString = builder.Configuration["ApplicationInsights:InstrumentationKey"]; }); builder.Services.Configure<LogoSettings>(builder.Configuration.GetSection("LogoSettings")); builder.Services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<LogoSettings>>().Value); builder.Services.AddScoped<IDataService, DataService>(); builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration.GetSection("AuthMessageSenderOptions")); builder.Services.AddScoped<IEmailSender<ApplicationUser>, EmailSender>(); builder.Services.AddScoped<IEmailSender, EmailSender>(); builder.Services.AddScoped<EmailSender>(); builder.Services.AddScoped<ICustomEmailSender, CustomEmailSender>(); builder.Services.AddScoped<CustomEmailSender>(); builder.Services.AddSingleton<BlobStorageService>(); builder.Services.AddHttpClient(); builder.Services.AddControllers(); var app = builder.Build(); // 配置HTTP请求管道 if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error"); // 默认HSTS值为30天,生产环境可按需修改 app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAntiforgery(); // app.UseAuthentication();// AI认为Blazor Server不需要,仅常规ASP.NET需要 app.UseAuthorization(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); // 添加Identity/Account Razor组件所需的额外端点 app.MapAdditionalIdentityEndpoints(); app.MapControllers(); app.Run(); }
内容的提问来源于stack exchange,提问作者Mark Evans
相关产品推荐
相关产品推荐

