At the place that I work to gain access to one of the databases we have
been supplied with a COM+ proxy that will allow us to connect. To
access the database we have impersonate a user to which they have
granted access to. Unfortunately the way that we were told to do this
was to write another COM+ class that will run as the user to which they
have granted access to, and allow this COM+ object to be accessed by
the user to which our web application runs under.
This sounded like a lot of work for nothing so I have tried to setup
the required impersonations within a class that exists within my
current project, just before the method call, but I have not been able
to make it work
I did do a search to try to find something that would help me out to
acheive what I want to do and below is the code that I found (along
with a couple tweaks). Unfortunately, calling on the methods within
the class does not do what I need it to do, since when I make the calll
to one of the methods in the COM+ class that I was supplied it gives me
an "Access Denied" error, and tells me that I am still running as the
ASPNET user.
If anyone knows of a way around this I would really appreciate some
input.
Thanks
namespace Mariner.WebParts.Security
{
/// <summary>
/// Jay Nathan - MARINER, LLC. - http://www.mariner-usa.com
///
/// Impersonator class allows client code to impersonate another
domain user account
/// by handling underlying account authentication and security
context manipulation
/// </summary>
public class Impersonator
{
public WindowsIdentity CurrentIdentity;
// private members for holding domain user account credentials
private string username = String.Empty;
private string password = String.Empty;
private string domain = String.Empty;
// this will hold the security context for reverting back to the
client after impersonation operations are complete
private WindowsImpersonationContext impersonationContext = null;
// disable instantiation via default constructor
private Impersonator() {}
public Impersonator(string username, string domain, string password)
{
// set the properties used for domain user account
this.username = username;
this.domain = domain;
this.password = password;
}
private WindowsIdentity Logon()
{
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
// attempt to authenticate domain user account
bool logonSucceeded = LogonUser(this.username, this.domain,
this.password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref
handle);
if(!logonSucceeded)
{
// if the logon failed, get the error code and throw an exception
int errorCode = Marshal.GetLastWin32Error();
throw new Exception("User logon failed. Error Number: " +
errorCode);
}
// if logon succeeds, create a WindowsIdentity instance
CurrentIdentity = new WindowsIdentity(handle);
// close the open handle to the authenticated account
CloseHandle(handle);
return CurrentIdentity;
}
public void Impersonate()
{
// authenticates the domain user account and begins impersonating it
this.impersonationContext = this.Logon().Impersonate();
CoImpersonateClient();
WindowsPrincipal princ = new WindowsPrincipal(CurrentIdentity);
System.Threading.Thread.CurrentPrincipal = princ;
}
public void Undo()
{
// rever back to original security context which was store in the
WindowsImpersonationContext instance
this.impersonationContext.Undo();
CoRevertToSelf();
}
[DllImport("ole32.dll")]
static extern int CoImpersonateClient () ;
[DllImport("ole32.dll")]
static extern int CoRevertToSelf () ;
public string WhoAmI()
{
// int i = CoImpersonateClient();
// if (i==0)
// {
//this returns the caller identity
string l_identity = Thread.CurrentPrincipal.Identity.Name ;
//CoRevertToSelf();
return l_identity ;
// }
// else
// throw new Exception ("CoImpersonateClient returned " + i.ToString
());
}
[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
}
}