You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:29:57