LogonUserEx, DuplicateTokenEx for Impersonation with an ObjectContext in C#

帅比萌擦擦* 提交于 2019-12-10 20:56:34

问题


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.

来源:https://stackoverflow.com/questions/8008049/logonuserex-duplicatetokenex-for-impersonation-with-an-objectcontext-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!