我正在使用ASP.Net Web API 2 / .Net 4.5.2。
我在排队后台工作项时试图保留调用主体。为此,我试图:
Thread.CurrentPrincipal = callingPrincipal;
但是当我这样做时,我得到一个ObjectDisposedException:
System.ObjectDisposedException:安全句柄已关闭
如何将当前主体保留在后台工作项中?
我可以以某种方式复制校长吗?
public void Run<T>(Action<T> action)
{
_logger.Debug("Queueing background work item");
var callingPrincipal = Thread.CurrentPrincipal;
HostingEnvironment.QueueBackgroundWorkItem(token =>
{
try
{
// UNCOMMENT - THROWS EXCEPTION
// Thread.CurrentPrincipal = callingPrincipal;
_logger.Debug("Executing queued background work item");
using (var scope = DependencyResolver.BeginLifetimeScope())
{
var service = scope.Resolve<T>();
action(service);
}
}
catch (Exception ex)
{
_logger.Fatal(ex);
}
finally
{
_logger.Debug("Completed queued background work item");
}
});
}
答案 0 :(得分:7)
结果manifestBlob += "\n";
manifestBlob += "// File: manifest.json\n";
manifestBlob += "//\n";
manifestBlob += "// Description:\n";
manifestBlob += "// manifest for chrome plug-in\n";
manifestBlob += "\n";
manifestBlob += "{\n";
manifestBlob += " \"manifest_version\": 2,\n";
manifestBlob += "\n";
manifestBlob += " \"version\": \"0.0.0\",\n";
manifestBlob += "\n";
manifestBlob += " // the ID is: sdfjkghsdfjkghjksdfghjkf
hjkdfjff\n";
manifestBlob += " \"key\": \"sdfjkhsdfjkghjksdfghkjsdhgs
djkgfhjklsdfhgjklsdfhgjklsdhfgkljsdfhgkljsdhklgjsdhfjklghsd
fjklghsdjklfghjksdfhgjksdhfgjklhsdfjkl\",\n";
manifestBlob += "\n";
manifestBlob += " \"content_scripts\": [ { \"matches\":
[\"http://*/*\", \"https://*/*\"], \"js\": [\"content.js\"]
, \"run_at\": \"document_start\" } ],\n";
manifestBlob += "\n";
manifestBlob += " // this is the standard LOCAL install
location - but if this extension is published to the app-st
ore, this value gets overridden (that is okay and even good
)\n";
manifestBlob += " \"update_url\": \"file:///C:/Program%2
0Files/MyProduct/Update.xml\",\n";
manifestBlob += "}\n";
现在有一个复制构造函数。
ClaimsPrincipal
这似乎可以在保留所有身份和声明信息的同时解决问题。完整的功能如下:
var principal = new ClaimsPrincipal(Thread.CurrentPrincipal);
答案 1 :(得分:0)
您的情况问题是在Thread.CurrentPrincipal
处置后执行的后台任务。这是因为ASP.NET模型 - 在用户上下文中处理请求,之后释放了与用户对应的所有值。所以这恰好发生在你的身份上。尝试保存有关用户及其身份的信息,以便以后模拟它。
您可以查看support article from Microsoft以模拟ASP.NET网站中的操作,但我不认为这会对您有所帮助:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =
((System.Security.Principal.WindowsIdentity)callingPrincipal.Identity).Impersonate();
//Insert your code that runs under the security context of the authenticating user here.
impersonationContext.Undo();
或者,可能是,您可以使用User.Token,如下所示:
HostingEnvironment.QueueBackgroundWorkItem(token =>
{
try
{
_logger.Debug("Executing queued background work item");
using (HostingEnvironment.Impersonate(callingPrincipal.Identity))
{
using (var scope = DependencyResolver.BeginLifetimeScope())
{
var service = scope.Resolve<T>();
action(service);
}
}
// UNCOMMENT - THROWS EXCEPTION
// Thread.CurrentPrincipal = callingPrincipal;
}
catch (Exception ex)
{
_logger.Fatal(ex);
}
finally
{
_logger.Debug("Completed queued background work item");
}
});
我建议您检查一下您的体系结构设计,以便找到一种方法将后台操作移出到其他上下文,其中用户身份将保持更长时间。其他方式,例如,使用将当前OperationContext
传递给Task
:
// store local operation context
var operationContext = OperationContext.Current;
TaskFactory.StartNew(() =>
{
// initialize the current operation context
OperationContext.Current = operationContext;
action();
})