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
相关产品推荐
相关产品推荐

