Skip to content
bitzorcas
中EN

Reference

现代多租户认证体系:JWT、API Key 与上下文注入

深入解析 BitzOrcas.Modern 企业级认证架构,掌握 ClaimsPrincipal 解析、API Key 高速验签、ICurrentUser 与 ICurrentTenant 统一上下文注入。

Last updated

在面向企业级 B2B SaaS 的开发中,身份认证(Authentication)远比简单的单租户登录复杂:

  • 多租户混合上下文:同一个用户可能隶属于多个租户企业,登录后必须清晰界定当前激活的 TenantId;
  • 双通道认证:既要支持前端浏览器基于 JWT 的用户交互认证,又要支持第三方开放平台基于 API Key / HMAC 签名的机器间认证;
  • 上下文篡改防范:严禁客户端在请求体中随意传递 UserId 或 TenantId 来冒充身份!

BitzOrcas.Modern 建立了统一的身份解析底座:通过 ASP.NET Core Authentication 中间件解析凭据,并在请求作用域(Scoped)内自动注入不可变的 ICurrentUser 与 ICurrentTenant。

身份认证与安全上下文注入全景

Bearer JWTX-API-Key

1. 入站 HTTP 请求

2. ASP.NET Core Authentication 中间件

3. JWT 签名与有效期校验

4. API Key / 机器凭据校验

5. 构造 ClaimsPrincipal 并注入安全上下文

6. ICurrentUser (UserId, Roles) + ICurrentTenant (TenantId)

7. 进入业务切片 Handler (从上下文安全读取身份)


第一步:从强类型上下文安全获取当前用户

在任何业务 Handler 中,严禁从 HTTP Body 或 Query 参数中读取 UserId。必须直接注入 ICurrentUser 与 ICurrentTenant:

SubmitOrderCommandHandler.cs: 安全读取身份上下文
using System;
using System.Threading;
using System.Threading.Tasks;
using BitzOrcas.Application.Abstractions.Security;
using BitzOrcas.Domain.Abstractions;
using BitzOrcas.Domain.Results;
public static class AuthErrors
{
public static readonly Error Unauthenticated =
Error.Unauthorized("Auth.Unauthenticated", "请先登录后再进行操作。");
}
public sealed class SubmitOrderCommandHandler(
ICurrentUser currentUser,
ICurrentTenant currentTenant,
ICommandRepository<Order, string> orderRepository)
{
public async ValueTask<Result<string>> Handle(SubmitOrderCommand command, CancellationToken ct)
{
// 1. 从经由服务端签名验证的安全上下文中提取有效用户 ID 与租户 ID
var userId = currentUser.UserId;
var tenantId = currentTenant.Tenant.EffectiveTenantId;
// 2. 校验用户是否处于有效登录态
if (string.IsNullOrEmpty(userId))
{
return Result<string>.Failure(AuthErrors.Unauthenticated);
}
// 3. 执行业务持久化(自动注入真实的 UserId 与 TenantId)
var order = Order.Create(
id: Guid.NewGuid().ToString("N"),
orderCode: command.OrderCode,
totalAmount: command.TotalAmount,
userId: userId,
tenantId: tenantId).GetValueOrThrow();
var saveResult = await orderRepository.SaveAsync(order, ct);
if (saveResult.IsFailure)
{
return Result<string>.Failure(saveResult.Error);
}
return Result<string>.Success(order.Id);
}
}

第二步:配置开放平台 API Key 认证通道

对于机器对机器(M2M)集成的 OpenAPI,通过注册 API Key 处理器实现高并发无状态验签:

ApiKeyAuthenticationHandler.cs: 机器通道验签
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
public sealed class ApiKeyAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
System.Text.Encodings.Web.UrlEncoder encoder,
IApiKeyValidator apiKeyValidator) : AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// 1. 从请求头提取 X-API-Key
if (!Request.Headers.TryGetValue("X-API-Key", out var apiKeyValue))
{
return AuthenticateResult.NoResult();
}
// 2. 校验 API Key 的合法性与有效租户绑定
var validationResult = await apiKeyValidator.ValidateKeyAsync(apiKeyValue.ToString());
if (validationResult.IsFailure)
{
return AuthenticateResult.Fail("API Key 无效或已过期。");
}
// 3. 构造代表机器客户端的 ClaimsPrincipal 身份主体
var identity = validationResult.Value!;
var ticket = new AuthenticationTicket(identity, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}

总结

BitzOrcas 的身份认证体系兼顾安全性与易用性:

  • 双通道统一:JWT 与 API Key 共享相同的下游授权上下文;
  • 防越权防篡改:上下文完全由服务端在网关层签名构造;
  • 多租户天然集成:自动解析有效租户,杜绝跨租户串号。

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%