我在 SQL CLR 中遇到了模拟问题。我在 .NET 4.5、SQL Server 2012 上工作。
我在http://webapitest.example.com/上有一个 WebAPI 服务,它启用了 Windows 身份验证并公开了一个方法 FileUpload (POST)。这是获取文件并将其存储在 SQL Server 数据库中的简单方法。服务由在专用帐户 DOMAIN\X 上运行的 IIS(7.5,Windows 2008R2)托管。
当我使用 Fiddler 调用此服务时,一切都很好。数据库中的服务存储文件作为当前 Windows 用户。
当我尝试在 SQL CLR 过程(下面的代码)中使用此 webAPI 方法时,会出现我的问题。CLR 过程在 SQL Server 帐户上下文 (DOMAIN\SQL) 中运行,因此我从 SqlContext 将内部过程模拟给用户。
[SqlProcedure]
public static void UploadBinaryContent([SqlFacet(MaxSize = -1)] byte[] vBytes, string serviceUrl)
{
WindowsIdentity clientId = null;
WindowsImpersonationContext impersonatedUser = null;
clientId = SqlContext.WindowsIdentity;
impersonatedUser = clientId.Impersonate();
HttpClientHandler handler = new HttpClientHandler()
{
UseDefaultCredentials = true
};
using (var client = new HttpClient(handler))
{
using (var content = new MultipartFormDataContent())
{
var fileContent = new ByteArrayContent(vBytes);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Foo.txt"
};
content.Add(fileContent);
string requestUri = serviceUrl;
try
{
if (impersonatedUser != null)
{
// this works as impersonated user ...
conn = new SqlConnection("Data Source=SERVER; Initial Catalog=WebAPITest;Trusted_Connection=True;");
conn.Open();
command = conn.CreateCommand();
command.CommandText = "SELECT 2";
command.CommandType = CommandType.Text;
command.ExecuteReader();
conn.Close();
// but this service is called by SQL Sever account
var httpResponseMessage = client.PostAsync(requestUri, content).Result;
}
}
finally
{
if (impersonatedUser != null)
{
impersonatedUser.Undo();
}
}
}
}
}
问题是,尽管模拟 WebAPI 服务尝试将文件作为 DOMAIN\SQL 放入数据库。有趣的是,调用直接 SQL 命令正在模拟用户上运行。
问题是如何以模拟用户身份使用 SQL CLR 过程中的 WebAPI 服务 POST 方法?