Skip to content
bitzorcas
中EN

Reference

细粒度资源与动作授权:IAuthorizedRequest 实践

告别粗糙混乱的 Role 角色硬编码!深入解析 BitzOrcas.Modern 基于资源与动作(Resource-Action)的细粒度授权引擎,掌握 IAuthorizedRequest 声明与动态决策。

Last updated

很多团队在做权限控制时,常常陷入“角色爆炸(Role Explosion)”的泥潭:

  • 代码里到处写着 [Authorize(Roles = "Admin,SuperAdmin,FinanceManager,Accountant")],只要新增一个业务角色,全仓几十处代码都要重新修改;
  • 无法做到“资源级动作控制”(例如允许查看财务报表,但禁止导出;允许修改草稿,但禁止发布)。

BitzOrcas.Modern 采用“资源与动作(Resource-Action)”细粒度授权模型:请求契约显式实现 IAuthorizedRequest,由 AuthorizationPipelineBehavior 在管道层自动查询当前用户的有效权限矩阵进行毫秒级判定。

资源动作授权流转全景

授权通过未获授权

1. 入站请求 (实现 IAuthorizedRequest)

2. AuthorizationPipelineBehavior

3. IAuthorizationDecisionService (评估当前用户针对 Resource + Action 的权限)

4. 执行业务 Handler

5. 短路返回 Result.Failure(403 Forbidden)


第一步:在请求契约上声明所需资源与动作

让 Command 或 Query 实现 IAuthorizedRequest:

ExportFinancialReportQuery.cs: 声明资源动作授权
using BitzOrcas.Application.Abstractions.Authorization;
using BitzOrcas.Domain.Results;
using Mediator;
namespace BitzOrcas.Finance.Contracts.Queries;
public sealed record ExportFinancialReportQuery(
string ReportYear) : IQuery<Result<byte[]>>, IAuthorizedRequest
{
// ① 声明受保护的目标资源为 "finance.report"
public ResourceDescriptor Resource { get; } = new("finance", "report");
// ② 声明本次请求所需的具体动作为 "Export"
public AuthorizationAction Action { get; } = AuthorizationAction.Export;
}

第二步:管道层自动化决策拦截

当请求进入时,管道提取用户的角色权限并调用决策服务:

AuthorizationPipelineBehavior.cs: 自动授权决策
using System.Threading;
using System.Threading.Tasks;
using BitzOrcas.Domain.Results;
public static class AuthorizationErrors
{
public static readonly Error PermissionDenied =
Error.Forbidden("Auth.PermissionDenied", "当前用户无权执行指定操作。");
}
public sealed class AuthorizationPipelineBehavior<TRequest, TResponse>(
IAuthorizationDecisionService decisionService,
ICurrentUser currentUser) : IPipelineBehavior<TRequest, TResponse>
where TRequest : IAuthorizedRequest
{
public async ValueTask<TResponse> Handle(
TRequest message,
CancellationToken cancellationToken,
MessageHandlerDelegate<TRequest, TResponse> next)
{
// 1. 评估当前用户是否拥有该资源的指定动作权限
var isAuthorized = await decisionService.HasPermissionAsync(
currentUser.UserId,
message.Resource,
message.Action,
cancellationToken);
if (!isAuthorized)
{
// 2. 权限不足:立即短路返回 403 Forbidden,绝不进入业务 Handler
return (TResponse)(object)Result.Failure(
AuthorizationErrors.PermissionDenied.WithDescription(
$"当前用户无权执行 {message.Resource.Name}:{message.Action} 操作。"));
}
// 3. 授权通过:放行进入 Handler
return await next(message, cancellationToken);
}
}

总结

资源与动作模型彻底解放了业务代码:

  • 零角色硬编码:业务代码只关心“需要什么动作权限”,角色如何分配由后台动态配置;
  • 细粒度控制:精准控制到“查看、创建、修改、删除、导出、审批”等每一个动作;
  • 全生命周期可审计:越权拦截自动触发安全审计告警。

100%

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