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

ASP.NET Core API中实现Hangfire多租户调度及面板隔离

实现步骤

1. 实现ScheduleSampleJob接口

首先定义接口接收参数的模型:

public class ScheduleJobRequest
{
    public string TenantID { get; set; }
    [JsonPropertyName("Cron Expression")]
    public string CronExpression { get; set; }
}

然后创建对应的API控制器:

[ApiController]
[Route("ScheduleSampleJob")]
public class ScheduleSampleJobController : ControllerBase
{
    private readonly IRecurringJobManager _recurringJobManager;
    private readonly IExecuteSimpleJob _executeJob;

    public ScheduleSampleJobController(IRecurringJobManager recurringJobManager, IExecuteSimpleJob executeJob)
    {
        _recurringJobManager = recurringJobManager;
        _executeJob = executeJob;
    }

    [HttpPost]
    public IActionResult CreateTenantJob([FromBody] ScheduleJobRequest request)
    {
        // 校验Cron表达式合法性
        if (!CronExpression.IsValid(request.CronExpression))
        {
            return BadRequest("Cron表达式格式错误");
        }
        // 作业ID带上租户标识,后续过滤用
        var jobId = $"Tenant_{request.TenantID}_SimpleExecuteJob";
        // 给任务添加租户标签,方便面板过滤
        var job = Job.FromExpression(() => _executeJob.Process(request.TenantID))
                     .WithTag($"Tenant:{request.TenantID}");
        
        _recurringJobManager.AddOrUpdate(jobId, job, request.CronExpression);
        return Ok($"租户{request.TenantID}的定时任务已创建/更新");
    }
}

记得同步调整IExecuteSimpleJob的Process方法,增加租户ID入参,方便任务执行时识别所属租户。

2. 配置Hangfire面板仅展示当前租户任务

要实现租户级的任务可见性隔离,需要做两处改造:

2.1 自定义Hangfire面板授权过滤器

先实现授权过滤器,同时获取当前登录用户所属的租户ID:

public class TenantHangfireAuthFilter : IDashboardAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        var httpContext = context.GetHttpContext();
        // 替换为实际业务的租户获取逻辑,比如从JWT、请求Header中解析
        var currentTenantId = httpContext.User.Claims.FirstOrDefault(c => c.Type == "TenantID")?.Value;
        if (string.IsNullOrWhiteSpace(currentTenantId))
        {
            return false;
        }
        // 存储当前租户ID到上下文,供后续过滤使用
        httpContext.Items["CurrentTenant"] = currentTenantId;
        // 可额外补充权限校验逻辑
        return true;
    }
}

2.2 配置面板过滤规则

在Configure方法中修改Hangfire面板注册逻辑,加入授权过滤器,同时配置作业列表过滤规则:

app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new TenantHangfireAuthFilter() },
    DisplayStorageConnectionString = false,
    IsReadOnlyFunc = ctx => false
});

要实现作业列表的过滤,最简单的方式是安装Hangfire.Tags扩展包,直接按标签过滤作业;也可以自定义查询逻辑,从存储中查询时自动加上租户ID前缀过滤条件。如果仅需要展示层过滤,直接在作业列表页用JS过滤也可以实现轻量效果,生产环境建议用后台查询过滤的方案。

注意事项

  • 你原来Configure方法中硬编码的全局定时任务可以删除,改为通过接口动态创建租户级任务
  • 如果需要更高的隔离级别,可以给每个租户配置独立的Hangfire存储Schema,这种方式不需要额外过滤逻辑,但是维护成本更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:48:02