use*_*582 8 .net c# sql-server active-directory sql-authentication
几天前我问了一个问题(使用Windows身份验证从非域计算机访问SQL Server 2005),这提出了一些有趣但不可用的建议.我想再次提出这个问题,但要弄清楚我的约束是什么:
我有一个Windows域,其中一台机器运行SQL Server 2005,并配置为仅支持Windows身份验证.我想在同一网络上的计算机上运行C#客户端应用程序,但不在域上,并访问SQL Server 2005实例上的数据库.
我不能在任何一台机器上创建或修改操作系统或SQL Server用户,我也不能对权限或模拟进行任何更改,我也不能使用runas.
我知道我可以使用以下四个参数编写可以连接到SQL Server数据库的Perl和Java应用程序:服务器名称,数据库名称,用户名(域名为domain\user)和密码.
在C#中,我尝试过各种各样的事情:
string connectionString = "Data Source=server;Initial Catalog=database;User Id=domain\user;Password=password";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
Run Code Online (Sandbox Code Playgroud)
并尝试将集成安全性设置为真假,但似乎没有任何效果.我想在C#中做什么根本不可能?
感谢任何帮助,马丁
我遇到了类似的问题,我正在编写一个工具,需要在一个域上的计算机上运行,并使用可信连接与另一个域上的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"
Run Code Online (Sandbox Code Playgroud)
/ netonly标志允许我用本地凭据执行exe并使用远程凭据访问网络,我想,无论如何我得到了我期望从远程服务器得到的结果集.问题是runas命令使调试应用程序变得非常困难,并且它闻起来不太好.
最后我发现这篇关于代码项目的文章正在讨论操作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();
Run Code Online (Sandbox Code Playgroud)
我添加了Undo方法,否则模仿对象往往会收集垃圾.我还修改了代码以使用LOGON32_LOGON_NEW_CREDENTIALS,但这是一个戳并运行以使其工作; 我仍然需要完全理解它的作用,我感觉它和runas上的/ netonly标志一样.我也打算稍微分解一下构造函数.
正如您所说,Linux 计算机上的 JDBC 或 Perl 都可以使用与当前登录用户不同的 Windows 身份验证和凭据连接到 SQL Server。顺便说一下,Windows CE 设备也是如此。
我认为这不是C#的问题,而是SQL Server OLE DB驱动程序的问题。我猜想上面提到的方法在网络级别上“假装是使用某些特定凭据的Windows计算机”;SQL Server OLE DB 驱动程序缺乏的功能。因此,我的建议是寻找一个可以访问 SQL Server 数据库的替代(也许是商业的?)OLE DB 驱动程序。不过,我不确定这样的事情是否存在。
| 归档时间: |
|
| 查看次数: |
5010 次 |
| 最近记录: |