gpt4 book ai didi

c# - WindowsImpersonationContext 下的程序集绑定(bind)。如何防止 FileLoadException?

转载 作者:行者123 更新时间:2023-11-30 12:18:43 24 4
gpt4 key购买 nike

由于跨 protected 网络共享移动和创建许多文件,我有一个需要进行大量模拟的应用程序。我创建了一个简单的静态类,它有一个方法接受用户、域、密码和一个包含您需要在模拟上下文中运行的代码的委托(delegate)。

我遇到的问题是当 CLR 尝试绑定(bind)到此上下文中的引用程序集时。随“访问被拒绝”消息一起抛出 FileLoadException。

我相信这是由于模拟用户没有足够的权限访问文件系统下的 *.DLL 文件。例如,我可以在模拟 block 之前编写良性代码,除了在上下文切换到模拟用户之前从问题程序集中加载类型外,它什么都不做,而且效果很好!然而,我真的不认为这是一个优雅的解决方案——我是否需要开始担心在模拟下我可以使用哪些类型,确保我事先放置随机的 typeof() 语句?

更令人沮丧的是我没有在我的本地开发机器上遇到这个问题。当程序集被运送到 beta 环境时,就会出现此问题。而且我无权从 Beta 环境读取文件权限以尝试在我的定位机器上模拟它们。

无论如何,我尝试了这个解决方案:

// Defined above:
// System.Security.Principal.WindowsIdentity identity;
// System.Security.Principal.WindowsImpersonationContext context;

context = identity.Impersonate();

int tries = 0;
while ( true )
{
try
{
contextAction();
}
catch ( FileLoadException ex )
{
if ( tries > MAX_TRIES )
{
// don't allow an infinite loop
throw;
}
if ( String.IsNullOrEmpty( ex.FileName ) )
{
// if this is null/empty, we can't really recover
throw;
}
context.Undo(); // return to current logon
try
{
var assemblyName = new AssemblyName( ex.FileName );
Assembly.Load( assemblyName );
tries++;
continue;
}
finally
{
context = identity.Impersonate(); // re-impersonate
}
}
finally
{
// return to your current windows logon
context.Undo();
}
}

没有骰子。我仍然收到“访问被拒绝”异常,除了现在从以 Assembly.Load 开头的行。

需要注意的一件有趣的事情是我从构建服务器得到了同样的异常。上述解决方案将其修复在构建服务器上。不在我们的测试版环境中。

我在这里错过了什么?谢谢。

最佳答案

我遇到了同样的问题。这似乎是模拟“ session ”没有被正确清理的问题。在调用您的逻辑之前加载问题程序集工作正常。在撤消和处理模拟标识和上下文后尝试加载程序集会导致另一个 FileLoadException。

Another thread显示了关闭 token 句柄的示例代码,但这样做对我的测试代码没有任何影响。

编辑

在模拟代码之前和之后调用 System.Security.Principal.WindowsIdentity.GetCurrent() 会返回相同的信息,即使必须进行某些更改以不再允许加载问题程序集。

编辑 #2(现在有 100% 更多的解决方案!)

我们刚刚在我们的网络应用程序中发现了一个单独的、严重得多的问题。创建标识和关闭句柄的过程不正确。我们的多线程应用程序出现了重大问题,最终导致我们的网站在所有句柄用完时陷入停顿。经过与其他开发人员的大量讨论和在线研究(包括 this thread 中倒数第二篇博文中的提示),我改进了代码,以便正确清理 token 句柄。

这似乎也解决了我们在模拟上下文中加载程序集的问题。无论我多么努力,我现在似乎都无法重现错误。我将在此处发布改进的模拟代码,以便您查看它是否适用于您的应用程序。注意 GetIdentity 中的锁 block ;这对于多线程应用程序非常重要。

// LogonType = 8        // LOGON32_LOGON_NETWORK_CLEARTEXT
// LogonProvider = 0 // LOGON32_PROVIDER_DEFAULT

[DllImport ( "advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true )]
private static extern bool LogonUser( string userName, string domain,
string password, int logonType, int logonProvider, ref IntPtr accessToken );

[DllImport ( "kernel32.dll", SetLastError = true )]
private static extern bool CloseHandle( IntPtr handle );

private static readonly object Locker = new Object ();

private static WindowsIdentity GetIdentity( string username, string domain, string password )
{
lock ( Locker )
{
IntPtr token = IntPtr.Zero;
if ( LogonUser ( username, domain, password,
(int) LogonType, (int) LogonProvider, ref token ) )
{
// using the token to create an instance of WindowsIdentity class
var identity = new WindowsIdentity ( token );
CloseHandle ( token ); // the WindowsIdentity object duplicates this token internally
return identity;
}

throw new SecurityException ( string.Format (
"Invalid username/password (domain: '{0}', username: '{1}')",
domain, username ) );
}
}

public static T ExecuteAction<T>( string username, string domain, string password,
Func<T> contextAction )
{
var identity = GetIdentity ( username, domain, password );
var context = identity.Impersonate ();
try
{

return contextAction ();
}
finally
{
context.Undo ();
context.Dispose ();
}
}

关于c# - WindowsImpersonationContext 下的程序集绑定(bind)。如何防止 FileLoadException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1499546/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com