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

使用Finbuckle实现租户级JWT认证遇问题及Cookie认证失效求助

问题解决方案

一、解决JWT认证中TenantInfo无JwtAuthority属性的错误

默认的TenantInfo类仅包含Id、Name、ConnectionString等基础属性,未定义JwtAuthority字段,需自定义租户类扩展属性:

  1. 创建自定义租户类
using Finbuckle.MultiTenant;

public class CustomTenantInfo : TenantInfo
{
    public string? JwtAuthority { get; set; }
}
  1. 配置文件添加租户JWT权限信息
    在appsettings.json中补充租户的JwtAuthority配置:
{
  "Finbuckle:MultiTenant:Stores:Configuration": {
    "Tenants": [
      {
        "Id": "tenant1",
        "Name": "TenantOne",
        "ConnectionString": "...",
        "JwtAuthority": "https://tenant1-auth.example.com"
      },
      {
        "Id": "tenant2",
        "Name": "TenantTwo",
        "ConnectionString": "...",
        "JwtAuthority": "https://tenant2-auth.example.com"
      }
    ]
  }
}
  1. 更新Program.cs的多租户与JWT配置
    替换泛型参数为自定义租户类,并添加JWT认证服务:
builder.Services.AddMultiTenant<CustomTenantInfo>()
    .WithHostStrategy()
    .WithConfigurationStore()
    .WithPerTenantOptions<JwtBearerOptions>((options, tenantInfo) =>
    {
        options.Authority = tenantInfo.JwtAuthority;
        options.Audience = "YourAudience";
        options.TokenValidationParameters.ValidateIssuerSigningKey = true;
    });

// 注册JWT认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer();

二、修复Cookie认证无法生成有效会话的问题

你的Cookie认证代码存在重复调用AddMultiTenant和中间件顺序错误的问题,修正如下:

  1. 修正多租户与认证配置
    仅调用一次AddMultiTenant,链式完成所有配置:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMultiTenant<TenantInfo>()
    .WithHostStrategy()
    .WithConfigurationStore()
    .WithPerTenantOptions<CookieAuthenticationOptions>((o, tenantInfo) =>
    {
        o.Cookie.Name = "SignInCookie-" + tenantInfo.Name;
    })
    .WithPerTenantAuthentication(); // 链式添加租户认证,无需重复调用AddMultiTenant

// 添加Cookie认证服务
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

builder.Services.AddDbContext<AppDbContext>();

var app = builder.Build();

// 中间件顺序必须严格遵循:多租户 → 认证 → 授权 → 路由
app.UseMultiTenant();
app.UseAuthentication();
app.UseAuthorization();
app.UseRouting();

// 后续添加端点配置...
  1. 添加登录端点生成认证Cookie
    Cookie认证不会自动生成会话,需实现登录逻辑创建Cookie:
app.MapPost("/login", async (HttpContext context) =>
{
    // 替换为实际用户验证逻辑
    bool isValidUser = true;
    if (isValidUser)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, "test-user"),
            new Claim(ClaimTypes.Role, "User")
        };

        var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
        var principal = new ClaimsPrincipal(identity);

        await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
        return Results.Ok("登录成功");
    }
    return Results.Unauthorized();
});

三、实现基于租户的JWT令牌生成

若目标是生成租户专属JWT令牌,需添加令牌颁发逻辑:

  1. 注册JWT生成服务
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer();

// 注册JWT生成器
builder.Services.AddSingleton<IJwtTokenGenerator, JwtTokenGenerator>();
  1. 实现JWT生成器
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public interface IJwtTokenGenerator
{
    string GenerateToken(string username, string tenantId, string tenantAuthority);
}

public class JwtTokenGenerator : IJwtTokenGenerator
{
    private readonly IConfiguration _config;

    public JwtTokenGenerator(IConfiguration config)
    {
        _config = config;
    }

    public string GenerateToken(string username, string tenantId, string tenantAuthority)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username),
            new Claim("TenantId", tenantId),
            new Claim("TenantAuthority", tenantAuthority)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: tenantAuthority,
            audience: "YourAudience",
            claims: claims,
            expires: DateTime.Now.AddHours(1),
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}
  1. 添加令牌生成端点
app.MapPost("/generate-token", (IJwtTokenGenerator tokenGenerator, IMultiTenantContextAccessor<CustomTenantInfo> tenantAccessor) =>
{
    var tenantInfo = tenantAccessor.MultiTenantContext?.TenantInfo;
    if (tenantInfo == null)
    {
        return Results.BadRequest("租户信息不可用");
    }

    var token = tokenGenerator.GenerateToken("test-user", tenantInfo.Id, tenantInfo.JwtAuthority);
    return Results.Ok(new { Token = token });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:27:08