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

Blazor WASM配置Negotiate+JWT双认证实现API访问保护

方案说明

你的设计思路完全可行:Windows认证仅用于初始访问时核验域用户身份,JWT只作为后续API访问的合法凭证,不需要承担用户身份认证的核心职能,这套逻辑非常适配企业内部域环境+Blazor WASM的部署场景。

之前配置失效的核心原因

你两次调用builder.Services.AddAuthentication()的写法是错误的:第二次调用会直接覆盖第一次注册的Negotiate(Windows认证)默认方案配置,最终只会保留最后一次注册的JwtBearer默认方案,导致两套认证逻辑都无法正常工作。ASP.NET Core不需要重复调用AddAuthentication,原生支持在一次认证注册中挂载多个认证方案。


具体实现步骤

不需要编写自定义中间件,用框架自带的多认证方案+授权策略就能实现全部需求。

1. 正确注册多认证方案

仅调用一次AddAuthentication,同时注册Windows认证和JWT认证两个方案:

using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

builder.Services.AddAuthentication(options =>
{
    // 初始获取Token的接口默认走Windows认证
    options.DefaultScheme = NegotiateDefaults.AuthenticationScheme;
})
.AddNegotiate()
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = true,
        ValidAudience = "xxx",
        ValidateIssuer = true,
        ValidIssuer = "xxx",
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWTSettings:Secret"]!))
    };
});

2. 配置分层授权规则

全局配置授权策略,实现接口权限隔离:

builder.Services.AddAuthorization(options =>
{
    // 默认全局策略:所有接口默认要求JWT认证,直接拦截无JWT的域用户直连请求
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build();
    
    // 单独策略:仅用于发放JWT的GetUser接口,走Windows认证
    options.AddPolicy("WindowsAuthOnly", policy =>
    {
        policy.AddAuthenticationSchemes(NegotiateDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser();
    });
});

// 注册中间件
app.UseAuthentication();
app.UseAuthorization();

给发放JWT的接口标记单独的授权策略:

[HttpGet]
[Route("GetUser")]
[Authorize(Policy = "WindowsAuthOnly")]
public UserModel GetUser()
{
    string? login =  httpContextAccessor!.HttpContext!.User?.Identity?.Name?.Replace("domain\\", "");
    return new UserModel{ UserName=login , JWT = CreateJWT(login)};
}

3. 开发环境放行Swagger

仅在开发环境跳过Swagger相关路径的授权校验,生产环境默认关闭:

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
    // 放行Swagger所有相关端点
    app.MapWhen(context => context.Request.Path.StartsWithSegments("/swagger"), appBuilder =>
    {
        appBuilder.Run(async context => await context.Response.NextAsync());
    });
}

4. Blazor WASM端适配

应用首次加载时先调用/GetUser接口,浏览器会自动携带Windows认证凭证,拿到返回的JWT后存储到本地,后续所有API请求都在请求头中携带Authorization: Bearer {JWT字符串}即可。


安全加固建议

  • JWT中增加专属应用标识声明,比如new Claim("ClientType", "InternalBlazorApp"),Token校验时强制验证该声明,进一步拦截非授权客户端的请求
  • JWT过期时间建议设置为15-30分钟,搭配静默刷新逻辑平衡安全性和使用体验
  • 生产环境必须移除Swagger放行规则,避免接口详情泄露

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:15:32