LogonUserEx、DuplicateTokenEx 用于在 C# 中使用 ObjectContext 进行模拟
我们有一个特定的 SQL Server,我们需要从厚客户端(.Net 4.0 WPF)访问它,并且我们可用于该连接的唯一凭据是“服务”帐户,该帐户实际上是具有 SQL 权限的 Active Directory 帐户服务器。
我在整个项目中使用实体框架和 ObjectContext,所以我在这里继续使用它。环顾四周后,我实现了一个基于 LogonUserEx 和 DuplicateTokenEx 的模拟例程,它允许我通过依赖注入编写以下内容:
using (container.Resolve<Impersonate>())
using (var context = container.Resolve<MyObjectContext>())
{
context.Connection.Open();
//Do some work with the data as the service account.
context.Connection.Close();
}
上面的 Impersonate 类的构造函数调用 LogonUserEx 等等。我明确打开和关闭连接作为工作单元模式的一部分,这不应该是相关的。
现在,通过调试我发现服务帐户的令牌已成功检索,并且用户被“模拟”。但是,一旦我尝试实例化 ObjectContext,就会收到以下错误:
System.TypeInitializationException: The type initializer for 'EntityBid' threw a
n exception. ---> System.IO.FileLoadException: Could not load file or assembly '
System.Data.Entity.dll' or one of its dependencies. Either a required impersonat
ion level was not provided, or the provided impersonation level is invalid. (Exc
eption from HRESULT: 0x80070542)
at System.Runtime.InteropServices.Marshal.GetHINSTANCE(RuntimeModule m)
at System.Runtime.InteropServices.Marshal.GetHINSTANCE(Module m)
at EntityBid.initEntryPoint()
at EntityBid.internalInitialize()
at EntityBid..cctor()
--- End of inner exception stack trace ---
at EntityBid.Trace(String fmtPrintfW, String a1)
at System.Data.EntityUtil.ProviderExceptionWithMessage(String message, Except
ion inner)
at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean op
enCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection
, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnection
OnFailure)
at System.Data.EntityClient.EntityConnection.Open()
at Core.Security.TestHarness._2.Class1..ctor()
因此,我模拟的帐户似乎不再具有访问权限或足够的权限来从 GAC 加载 DLL。 Fusion 日志没有提供任何附加信息。
我不知道如何解决这个问题。我想知道我当前是否没有检索到具有足够权限的令牌。请注意,我向 LogonUserEx 提供以下参数:LOGON32_LOGON_NETWORK_CLEARTEXT 和 LOGON32_PROVIDER_DEFAULT。
最后,请注意,此过程在登录用户具有管理权限的计算机上绝对可以正常工作。当我在具有“普通”帐户的用户上运行它时(受通常的公司 GPO 约束),它会崩溃!
编辑:只是为了包含模拟的“重要”部分。请注意,我现在已切换到 LOGON32_LOGON_UNLOCK,因为它工作得更好。对于稍有问题的格式表示歉意:
if (LogonUserEx(dUser, dDomain, dPassword, LOGON32_LOGON_UNLOCK,
LOGON32_PROVIDER_DEFAULT, out token, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
{
if (DuplicateTokenEx(token, MAXIMUM_ALLOWED, ref sa, SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, TOKEN_TYPE.TokenPrimary, out tokenDuplicate))
{
m_ImpersonatedUser = new WindowsIdentity(token);
_windowsImpersonationContext = m_ImpersonatedUser.Impersonate();
非常感谢任何帮助。
缺口。
We have a particular SQL Server which we need to access from a thick (.Net 4.0 WPF) client, and the only credentials available to us for that connection is a 'service' account which is effectively an Active Directory account with permission on the SQL Server.
I am using Entity Framework, and ObjectContext, throughout the project, so am continuing with it here. After looking around, I have implemented an impersonation routine based on LogonUserEx, and DuplicateTokenEx, which allows me, via Dependency Injection, to write the following:
using (container.Resolve<Impersonate>())
using (var context = container.Resolve<MyObjectContext>())
{
context.Connection.Open();
//Do some work with the data as the service account.
context.Connection.Close();
}
The constructor of the Impersonate class above calls LogonUserEx and so on. I am explicitly opening and closing the connection as part of a Unit Of Work pattern, which shouldn't be relevant.
Now, via debugging I have found that the token is successfully retrieved for the service account and the user is 'impersonated'. However, as soon as I try to instantiate the ObjectContext I get the following error:
System.TypeInitializationException: The type initializer for 'EntityBid' threw a
n exception. ---> System.IO.FileLoadException: Could not load file or assembly '
System.Data.Entity.dll' or one of its dependencies. Either a required impersonat
ion level was not provided, or the provided impersonation level is invalid. (Exc
eption from HRESULT: 0x80070542)
at System.Runtime.InteropServices.Marshal.GetHINSTANCE(RuntimeModule m)
at System.Runtime.InteropServices.Marshal.GetHINSTANCE(Module m)
at EntityBid.initEntryPoint()
at EntityBid.internalInitialize()
at EntityBid..cctor()
--- End of inner exception stack trace ---
at EntityBid.Trace(String fmtPrintfW, String a1)
at System.Data.EntityUtil.ProviderExceptionWithMessage(String message, Except
ion inner)
at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean op
enCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection
, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnection
OnFailure)
at System.Data.EntityClient.EntityConnection.Open()
at Core.Security.TestHarness._2.Class1..ctor()
Consequently, it would appear that the account I am impersonating no longer has access or sufficient privelage to load the DLL's from the GAC. The Fusion log is not giving any additional information.
I am not sure how to solve this. I wonder if I am not currently retrieving a token with sufficient privelage. Note that I am providing these paramteres to LogonUserEx: LOGON32_LOGON_NETWORK_CLEARTEXT and LOGON32_PROVIDER_DEFAULT.
Finally, note that this process works absolutely fine on a machine with administrative privelages for the logged on user. It breaks when I run it on a user with a 'normal' account, subject to the usual corporate GPO!
EDIT: Just to include the 'important' part of the impersonation. Notice that I have now swapped to LOGON32_LOGON_UNLOCK, as it is working better. Apologies for the slightly iffy formatting:
if (LogonUserEx(dUser, dDomain, dPassword, LOGON32_LOGON_UNLOCK,
LOGON32_PROVIDER_DEFAULT, out token, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
{
if (DuplicateTokenEx(token, MAXIMUM_ALLOWED, ref sa, SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, TOKEN_TYPE.TokenPrimary, out tokenDuplicate))
{
m_ImpersonatedUser = new WindowsIdentity(token);
_windowsImpersonationContext = m_ImpersonatedUser.Impersonate();
Any help greatly appreciated.
Nick.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论