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

如何在HotChocolate中实现订阅的动态授权及权限变更管控?

为HotChocolate订阅实现动态主题授权(基于SSE)

一、初始订阅权限校验

在订阅建立阶段直接拦截无权限请求,避免无效连接建立。通过自定义授权策略解析主题中的订单ID,校验用户权限:

  1. 定义授权需求与处理器:
public class OrderSubscriptionRequirement : IAuthorizationRequirement { }

public class OrderSubscriptionAuthorizationHandler : AuthorizationHandler<OrderSubscriptionRequirement>
{
    private readonly IOrderPermissionService _permissionService;

    public OrderSubscriptionAuthorizationHandler(IOrderPermissionService permissionService)
    {
        _permissionService = permissionService;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OrderSubscriptionRequirement requirement)
    {
        if (context.Resource is ISubscriptionEventContext subContext)
        {
            // 从主题提取订单ID
            var orderId = subContext.Topic.Split('_').Last();
            var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
            
            if (await _permissionService.HasAccess(userId, orderId))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }
    }
}
  1. 注册授权策略并应用到订阅字段:
services.AddAuthorization(options =>
{
    options.AddPolicy("OrderSubscribe", policy =>
        policy.AddRequirements(new OrderSubscriptionRequirement()));
});

// 订阅字段配置
[Subscribe(With = typeof(OrderUpdatedSubscription))]
[Authorize(Policy = "OrderSubscribe")]
public OrderUpdated? OrderUpdated([EventMessage] OrderUpdated message) => message;

无权限用户发起订阅时会直接收到授权失败响应,无法建立连接。

二、动态权限失效的实时处理

针对权限随订单状态变化的场景,有两种核心实现方式:

方案1:推送前实时校验权限

在订阅事件流的处理逻辑中,每次推送前重新校验权限,无权限则终止流:

public class OrderUpdatedSubscription : ISubscriptionResolver<OrderUpdated>
{
    private readonly IOrderPermissionService _permissionService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public OrderUpdatedSubscription(IOrderPermissionService permissionService, IHttpContextAccessor httpContextAccessor)
    {
        _permissionService = permissionService;
        _httpContextAccessor = httpContextAccessor;
    }

    public async ValueTask<IAsyncEnumerable<OrderUpdated>> ResolveAsync(ISubscriptionEventContext context, CancellationToken cancellationToken)
    {
        var orderId = context.Topic.Split('_').Last();
        var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
        var updateStream = await GetOrderUpdateStream(orderId, cancellationToken);

        await foreach (var update in updateStream.WithCancellation(cancellationToken))
        {
            if (!await _permissionService.HasAccess(userId, orderId))
            {
                // 终止流,断开订阅
                break;
            }
            yield return update;
        }
    }
}

方案2:权限变化时主动断开订阅

维护用户与订阅连接的映射,当权限失效时主动关闭对应连接:

public class OrderPermissionChangedHandler
{
    private readonly ISubscriptionManager _subscriptionManager;

    public OrderPermissionChangedHandler(ISubscriptionManager subscriptionManager)
    {
        _subscriptionManager = subscriptionManager;
    }

    public async Task OnPermissionLost(string userId, string orderId)
    {
        var targetTopic = $"OrderUpdated_{orderId}";
        var subscriptions = _subscriptionManager.GetSubscriptions(targetTopic);

        foreach (var sub in subscriptions)
        {
            var subUserId = sub.Context.User.FindFirstValue(ClaimTypes.NameIdentifier);
            if (subUserId == userId)
            {
                await _subscriptionManager.UnsubscribeAsync(sub.Id);
            }
        }
    }
}

在订单状态变更触发权限失效时,调用该方法即可断开用户的对应订阅。

三、避免订单ID泄露的优化

  • 禁止无权限用户建立订阅:初始校验不通过直接拒绝,用户无法获取任何关于主题存在性的信息。
  • 加密主题中的订单ID:生成主题时使用加密后的订单ID,避免原始ID泄露:
    var encryptedOrderId = Encrypt(orderId);
    var topic = $"OrderUpdated_{encryptedOrderId}";
    

四、SSE适配要点

  • 初始权限校验要在SSE连接建立的HTTP请求阶段完成,避免无效连接占用资源。
  • 权限失效时主动关闭SSE连接,返回403状态码,让客户端明确感知权限变化。
  • 终止事件流时确保SSE连接正常关闭,避免客户端无意义等待。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:02:50