在与排队的用户不同的进程中运行后台作业

Posted

技术标签:

【中文标题】在与排队的用户不同的进程中运行后台作业【英文标题】:Run a background job in a different process as the user who queued it 【发布时间】:2016-11-15 14:18:10 【问题描述】:

在我们的应用程序中,我们有要在后台运行的 Web API 排队作业。我们使用 HangFire 进行作业的后台处理。 Web API 使用 Windows 身份验证。 Hangfire 服务器配置为作为 Windows 服务运行。

我正在尝试以将它们排队的同一用户的身份执行后台作业。

我尝试传递 WindowsIdentity.GetCurrent()(序列化并由 hangfire 传递)抛出的异常是“用于模拟的令牌无效 - 它不能被复制”

[HttpGet, Route("enq")]
public IHttpActionResult EnQueue(string country)
     
    var curUser = System.Security.Principal.WindowsIdentity.GetCurrent();           
    var id = Hangfire.BackgroundJob.Enqueue(() => Services.Common.TestClass.Test(curUser , country));
    return Ok(id);

遇到了一种调用WIN32 API method Logon user 的方法。但是由于它需要密码作为输入,因此不知道如何使用它。

有什么方法可以将后台作业作为排队的同一用户执行?

【问题讨论】:

一个WindowsIdentity 对象引用了一个句柄,它是一个内核对象,因此不能被序列化。 Hangfire 必须在作业排队时显式复制用户的令牌。 (我不知道它是否已经可以做到这一点,或者如果没有,添加会有多难。) 好的,谢谢@HarryJohnston! 【参考方案1】:

可能的解决方案:

    使用 Win32 API 调用。缺点是,这种方法需要用户密码。下面的 SO 问题中有更多详细信息。

Windows Impersonation and duplicating tokens

    使用 Kerberos 扩展“用户登录服务”

https://blogs.msdn.microsoft.com/winsdk/2015/08/28/logon-as-a-user-without-a-password/

var upn = System.DirectoryServices.AccountManagement.UserPrincipal.Current.UserPrincipalName;
WindowsIdentity s4u = new WindowsIdentity(upn);

【讨论】:

以上是关于在与排队的用户不同的进程中运行后台作业的主要内容,如果未能解决你的问题,请参考以下文章

Centos进程作业管理与计划任务

shell后台执行命令-crontab

HapiJS 启动更长的后台进程

Self-Hosted Github Runner:在作业中启动一个后台服务器进程,让它在作业结束后运行

用户启动的后台进程数量有限

在 Rails 中运行大量长时间运行的后台作业