Windows 和 .NET 中的凭据链接序列出现问题
本文关键字:问题 链接 NET Windows | 更新日期: 2023-09-27 17:56:17
问题摘要
当以批处理模式运行时,我的用户身份会丢失,但(就像一个非常好的悬崖峭壁)直到最后一刻。
问题详情
我有一个在WinXpSp3上运行的PowerShell脚本,该脚本在后台(通过-AsJob参数)作为特定测试用户(通过-Session参数)在远程计算机上运行脚本块(通过Invoke-Command)。会话是通过以下方式创建的:
New-PSSession -computername $myServer -credential $myCredential
脚本块执行许多操作,最终运行 NUnit 测试框架。测试中的C#代码记录了"myTestUser"用户名(通过Environment.UserName
),因此到目前为止,PowerShell提供的凭据可以正确接收。Process Explorer进一步证实了这一点:检查运行批处理测试的nunit控制台的属性表明它归myTestUser所有。
该测试包括访问 Sql Server 2008 R2 数据库;连接字符串是通过new SqlConnection(connectionString)
调用设置的。连接字符串是为 Windows 身份验证设置的,并使用以下形式:
Data Source=<my_db_server_name>;Initial Catalog=<my_db_name>;Integrated Security=True;Persist Security Info=True
即使我最终将 myTestUser 凭据一直推送到受测的 C# 代码,数据库访问尝试也没有看到这些凭据,从而导致此错误: 用户"NT 权限''匿名登录"登录失败
一些补充信息:
- 我已确认测试用户 (myTestUser) 具有数据库权限,并且 NUnit 测试能够访问数据库:当我以 myTestUser 身份登录的手动运行 NUnit 测试(通过 NUnit GUI)时,测试工作正常,并且 SqlProfiler 清楚地显示了此活动,myTestUser 出现在 NTUserName 列中。
- 如果我在本地而不是在远程计算机上运行,则会发生相同的错误。
- 如果我在本地机器上以自己的身份运行(即省略 -credential 参数),也会发生同样的错误。
问题
我怎样才能将myTestUser从厄运的边缘拯救出来,并让他获得数据库访问权限?
2011.05.16 更新
下面是一个显示相同问题的简化示例。
首先,我的测试程序DBFetchVersion打印当前用户的名称和简单查询的结果:
class Program
{
const string connString = ...your connection string here... ;
const string query = "SELECT getdate() [Date], substring(@@version,1,charindex('-',@@version)-1) +convert(varchar(100),SERVERPROPERTY('edition'))+ ' ' +convert(varchar(100),SERVERPROPERTY('productlevel')) [SQL Server Version], @@servicename [Service Name], @@servername [Server Host], db_name() [Database], user_name() [User], host_name() [Client]";
static void Main(string[] args)
{
DataView dataView;
using (var connection = new SqlConnection(connString))
{
Console.WriteLine("user = " + Environment.UserName);
using (var dataAdapter = new SqlDataAdapter(query, connection))
{
var dataSet = new DataSet();
try
{
connection.Open();
dataAdapter.SelectCommand.CommandType = CommandType.Text;
dataAdapter.Fill(dataSet, query);
}
finally { if (connection.State == ConnectionState.Open) connection.Close(); }
dataView = dataSet.Tables[0].DefaultView;
}
foreach (var item in dataView.Table.Rows[0].ItemArray)
Console.WriteLine(item);
}
}
}
这是调用上述程序的Powershell脚本。
$scriptBlock = {
& "...path to my executable...'DBFetchVersion'bin'Debug'DBFetchVersion.exe"
}
$serverName = ... my server name ...
$username = "testuser"
$password = ... my user password ...
$adjPwd = $password | ConvertTo-SecureString -asPlainText -Force
$testCred = (New-Object System.Management.Automation.PSCredential($username,$adjPwd))
$mySession = New-PSSession -computername $serverName -credential $testCred
# Test Scenarios:
Invoke-Command $scriptBlock
#Invoke-Command $scriptBlock -computername $serverName
#Invoke-Command $scriptBlock -computername $serverName -credential $testCred
#Invoke-Command $scriptBlock -Session $mySession
在最后的四个测试方案列表中,未注释的测试方案有效,打印我的用户名和查询结果。DBFetchVersion 仍然报告我是第二行的用户,但数据库连接失败,并显示"用户'NT AUTHORITY''ANONYMOUS 登录'登录失败"错误。其余两行报告"testuser"用户名,但都报告数据库连接的相同登录失败。
这个孤立的例子告诉我的并不是我认为Powershell,.NET或我的代码有任何错误,而是身份验证机制中有一些我还不了解的东西,因为指定另一台计算机或会话都涉及路径,从某种意义上说,应该具有更强的保护。
2011.08.03 更新 - 尤里卡!
好吧,Matt 正确地将双跳问题确定为罪魁祸首,将 CredSSP 身份验证确定为解决方案。不幸的是,正如我很快发现的那样,CredSSP需要Windows 7,所以我开始设置几个VM作为沙盒。然而,CredSSP不是一个轻易放弃其秘密的人(至少对我来说),正如我在ServerFault上的这篇文章中所详述的那样:无法让CredSSP身份验证在PowerShell中工作。
我终于能够让 CredSSP 身份验证正常工作,这样我就可以回到我在此线程中提出的问题。作为测试,我使用了插入到上面提供的PowerShell脚本中的以下3个脚本块:
$scriptBlockA = {
Write-Host ("hello, world: {0}, {1}" -f $env:USERNAME, (hostname))
}
# Simple DB test, but requires SqlServer installed!
$scriptBlockB = {
if (! (Get-PSSnapin | ? { $_.name -eq "SqlServerCmdletSnapin100" } ) )
{ Add-PSSnapin SqlServerCmdletSnapin100; }
Invoke-Sqlcmd -Query "SELECT getdate() as [Now]" -ServerInstance CinDevDB5
}
# Indirect DB test; requires .NET but not SqlServer,
# plus DBFetchVersion in home dir for targeted user.
$scriptBlockC = {
& ".'DBFetchVersion.exe"
}
A块使用或不使用CredSSP,因为没有双跳。块 B 和 C 仅适用于 CredSSP,因为它们都尝试访问远程数据库。QED。
最初我读到这篇文章并想到了"双跳"问题,但补充信息可能让我质疑这一点。
当您在本地运行它(作为您自己或测试用户)时,您使用什么命令? 这个:
& "...path to my executable...'DBFetchVersion'bin'Debug'DBFetchVersion.exe"
也可以从本地计算机(作为您自己或用户)执行此工作:
Add-PSSnapin SqlServerCmdletSnapin100;
Invoke-Sqlcmd -Query "SELECT getdate()" -ServerInstance Server
还有你用的是什么操作系统?如果是Windows 2008并且问题是双跳,您可以向我们CredSSP避免它。