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

Blazor Server应用混合认证方案问题:移动端Windows认证异常

问题:Blazor Server 移动端Windows认证异常及API匿名访问配置

现状

Blazor Server应用核心功能基于Windows Authentication(Negotiate方案)运行正常,配套API接口使用Bearer Token认证也能正常工作。但在非Windows设备(如移动端)访问时,出现认证异常:完成登录后短暂显示用户身份,几秒后自动切换为匿名状态。需要解决移动端Windows认证的稳定性问题,同时将API调整为支持匿名访问。

现有代码片段

Program.cs

builder.Services.AddScoped<AuthenticationStateProvider, RoleAuthenticationStateProvider>();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
                .AddNegotiate()
                .AddScheme<AuthenticationSchemeOptions, BearerAuthHandler>("Bearer", null);

// 其他初始化代码

app.UseAuthorization();

App.razor

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

MyAPIController.cs

[Authorize(AuthenticationSchemes = "Bearer")]
[Route("api/[controller]")]
[ApiController]
public class MyAPIController : ControllerBase
{
    // API方法
}

解决方案

1. 修复移动端Windows认证会话丢失问题

移动端浏览器对Negotiate协议的支持存在限制,容易导致认证状态无法持久化。通过添加Cookie认证作为回退方案,确保跨设备的认证状态稳定:

修改Program.cs中的认证配置,加入Cookie认证:

using Microsoft.AspNetCore.Authentication.Cookies;

// ...

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
                .AddNegotiate()
                .AddCookie(options =>
                {
                    options.Cookie.HttpOnly = true;
                    // 生产环境建议设为Always,本地测试可改为None
                    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
                    options.ExpireTimeSpan = TimeSpan.FromHours(8);
                    options.SlidingExpiration = true;
                    // 设置登录路径(如果需要)
                    options.LoginPath = "/login";
                })
                .AddScheme<AuthenticationSchemeOptions, BearerAuthHandler>("Bearer", null);

同时,确保自定义的RoleAuthenticationStateProvider能够正确处理Cookie认证生成的ClaimsPrincipal,避免错误地将已认证用户标记为匿名。

2. 配置API支持匿名访问

要让API允许匿名访问,直接移除原有的[Authorize]特性,或添加[AllowAnonymous]特性:

[AllowAnonymous]
[Route("api/[controller]")]
[ApiController]
public class MyAPIController : ControllerBase
{
    // 所有接口允许匿名访问
}

如果需要保留部分接口的Bearer认证,可在特定方法上单独添加[Authorize]:

[AllowAnonymous]
[Route("api/[controller]")]
[ApiController]
public class MyAPIController : ControllerBase
{
    [HttpGet("public")]
    public IActionResult GetPublicData()
    {
        return Ok("公开数据");
    }

    [Authorize(AuthenticationSchemes = "Bearer")]
    [HttpGet("private")]
    public IActionResult GetPrivateData()
    {
        return Ok("需Bearer认证的数据");
    }
}

3. 统一Blazor页面的授权策略

在Program.cs中配置默认授权策略,允许Negotiate和Cookie两种认证方案的用户访问受保护页面:

builder.Services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder(
        NegotiateDefaults.AuthenticationScheme,
        CookieAuthenticationDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build();
});

这样Blazor的AuthorizeRouteView会同时认可Windows设备的Negotiate认证和移动端的Cookie认证,避免身份切换异常。


内容的提问来源于stack exchange,提问作者Jeff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:28:15