我有一個類似的問題,我正在編寫一個工具,需要在一個域上的計算機上運行,並使用可信連接與另一個域上的SQL服務器進行身份驗證。我所能找到的關於這個問題的一切都說不能做到。相反,您必須加入域名,使用SQL身份驗證,加入Kerberos的一些參與者,或者讓您的網絡人員建立一個可信賴的關係,以提供一些替代方案。
是我知道我能得到它使用RUNAS某些方面的工作,因爲我已經有SSMS證明了它的事情:
C:\WINDOWS\system32\runas.exe /netonly /savecred /user:megacorp\joe.bloggs "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\SqlWb.exe"
的/ netonly標誌讓我與本地憑據執行.exe和使用遠程憑證訪問網絡,無論如何,我從遠程服務器獲得了我期望的結果集。問題在於runas命令使調試應用程序變得非常困難,而且沒有良好的氣味。
最終我發現這篇文章上the code project這是談論驗證操作的Active Directory,這是確實的模擬主類:
using System;
using System.Runtime.InteropServices; // DllImport
using System.Security.Principal; // WindowsImpersonationContext
namespace TestApp
{
class Impersonator
{
// group type enum
enum SECURITY_IMPERSONATION_LEVEL : int
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
extern static bool CloseHandle(IntPtr handle);
// creates duplicate token handle
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
WindowsImpersonationContext newUser;
///
/// Attempts to impersonate a user. If successful, returns
/// a WindowsImpersonationContext of the new users identity.
///
/// Username you want to impersonate
/// Logon domain
/// User's password to logon with
///
public Impersonator(string sUsername, string sDomain, string sPassword)
{
// initialize tokens
IntPtr pExistingTokenHandle = new IntPtr(0);
IntPtr pDuplicateTokenHandle = new IntPtr(0);
pExistingTokenHandle = IntPtr.Zero;
pDuplicateTokenHandle = IntPtr.Zero;
// if domain name was blank, assume local machine
if (sDomain == "")
sDomain = System.Environment.MachineName;
try
{
const int LOGON32_PROVIDER_DEFAULT = 0;
// create token
// const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
//const int SecurityImpersonation = 2;
// get handle to token
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
// did impersonation fail?
if (false == bImpersonated)
{
int nErrorCode = Marshal.GetLastWin32Error();
// show the reason why LogonUser failed
throw new ApplicationException("LogonUser() failed with error code: " + nErrorCode);
}
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);
// did DuplicateToken fail?
if (false == bRetVal)
{
int nErrorCode = Marshal.GetLastWin32Error();
CloseHandle(pExistingTokenHandle); // close existing handle
// show the reason why DuplicateToken failed
throw new ApplicationException("DuplicateToken() failed with error code: " + nErrorCode);
}
else
{
// create new identity using new primary token
WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
newUser = impersonatedUser;
}
}
finally
{
// close handle(s)
if (pExistingTokenHandle != IntPtr.Zero)
CloseHandle(pExistingTokenHandle);
if (pDuplicateTokenHandle != IntPtr.Zero)
CloseHandle(pDuplicateTokenHandle);
}
}
public void Undo()
{
newUser.Undo();
}
}
}
只使用它:
Impersonator impersonator = new Impersonator("username", "domain", "password");
//Connect to and use SQL server
impersonator.Undo();
我在撤消方法中添加了否則模擬器對象傾向於垃圾收集。我還修改了代碼以使用LOGON32_LOGON_NEW_CREDENTIALS,但這是一個捅捅並運行以使其工作;我仍然需要充分理解它的作用,我覺得它和runas上的/ netonly標誌是一樣的。我也打算分解一下構造函數。
實際上,這個問題很清楚地表明,使用SQL Server身份驗證不是一個選項(儘管...沒有downvote) – Heinzi 2010-08-22 07:49:21