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 ユーザーとしての DB 内のサービス ストア ファイル。
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 として DB に配置しようとすることです。興味深いことに、直接 SQL コマンドを呼び出すと、偽装されたユーザーで実行されます。
問題は、偽装ユーザーとして SQL CLR プロシージャ内で WebAPI サービスの POST メソッドをどのように使用できるかということです。