Saya memiliki aplikasi web (dihosting di IIS) yang berbicara ke layanan Windows. Layanan Windows menggunakan ASP.Net MVC Web API (self-host), dan dapat dikomunikasikan dengan lebih dari http menggunakan JSON. Aplikasi web dikonfigurasi untuk melakukan peniruan, gagasannya adalah bahwa pengguna yang membuat permintaan ke aplikasi web harus menjadi pengguna yang digunakan aplikasi web untuk membuat permintaan ke layanan. Strukturnya terlihat seperti ini:
(Pengguna yang disorot dengan warna merah adalah pengguna yang dirujuk dalam contoh di bawah ini.)
Aplikasi web membuat permintaan ke layanan Windows menggunakan HttpClient
:
var httpClient = new HttpClient(new HttpClientHandler()
{
UseDefaultCredentials = true
});
httpClient.GetStringAsync("http://localhost/some/endpoint/");
Ini membuat permintaan ke layanan Windows, tetapi tidak melewati kredensial dengan benar (layanan melaporkan pengguna sebagai IIS APPPOOL\ASP.NET 4.0
). Ini bukan yang saya inginkan terjadi .
Jika saya mengubah kode di atas untuk menggunakan WebClient
, kredensial pengguna diberikan dengan benar:
WebClient c = new WebClient
{
UseDefaultCredentials = true
};
c.DownloadStringAsync(new Uri("http://localhost/some/endpoint/"));
Dengan kode di atas, layanan melaporkan pengguna sebagai pengguna yang membuat permintaan ke aplikasi web.
Apa yang saya lakukan salah dengan HttpClient
implementasi yang menyebabkannya tidak lulus kredensial dengan benar (atau apakah itu bug dengan HttpClient
)?
Alasan saya ingin menggunakan HttpClient
adalah karena ia memiliki API async yang bekerja dengan baik dengan Task
s, sedangkan WebClient
API asyc perlu ditangani dengan acara.
sumber
DownloadStringTaskAsync
.Net 4.5, yang juga dapat digunakan dengan async / menungguHttpClient
tidak punyaSetCredentials()
metode. Bisakah Anda mengarahkan saya ke maksud Anda?new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true, UseDefaultCredentials = true }
di server web yang diakses oleh pengguna terotentikasi Windows, dan situs web melakukan otentikasi untuk sumber daya jarak jauh lain setelah itu (tidak akan mengotentikasi tanpa flag yang ditetapkan).Jawaban:
Saya juga mengalami masalah yang sama. Saya mengembangkan solusi sinkron berkat penelitian yang dilakukan oleh @tpeczek dalam artikel SO berikut: Tidak dapat mengautentikasi ke layanan ASP.NET Web Api dengan HttpClient
Solusi saya menggunakan a
WebClient
, yang seperti yang Anda catat dengan benar melewati kredensial tanpa masalah. AlasannyaHttpClient
tidak berhasil adalah karena keamanan Windows menonaktifkan kemampuan untuk membuat utas baru di bawah akun tiruan (lihat artikel SO di atas.)HttpClient
Membuat utas baru melalui Pabrik Tugas sehingga menyebabkan kesalahan.WebClient
di sisi lain, berjalan secara sinkron di utas yang sama sehingga melewati aturan dan meneruskan kredensial.Meskipun kodenya berfungsi, downside adalah bahwa itu tidak akan berfungsi async.
Catatan: Memerlukan paket NuGet: Newtonsoft.Json, yang merupakan serializer JSON yang digunakan WebAPI.
sumber
Anda dapat mengonfigurasi
HttpClient
untuk meneruskan kredensial seperti ini:sumber
Apa yang Anda coba lakukan adalah membuat NTLM meneruskan identitas ke server berikutnya, yang tidak dapat dilakukan - itu hanya dapat melakukan peniruan yang hanya memberi Anda akses ke sumber daya lokal. Itu tidak akan membiarkan Anda melewati batas mesin. Otentikasi Kerberos mendukung delegasi (apa yang Anda butuhkan) dengan menggunakan tiket, dan tiket dapat diteruskan ketika semua server dan aplikasi dalam rantai dikonfigurasikan dengan benar dan Kerberos diatur dengan benar di domain. Jadi, singkatnya Anda perlu beralih dari menggunakan NTLM ke Kerberos.
Untuk lebih lanjut tentang opsi Otentikasi Windows yang tersedia untuk Anda dan cara kerjanya mulai dari: http://msdn.microsoft.com/en-us/library/ff647076.aspx
sumber
WebClient
? Ini adalah hal yang saya tidak mengerti - jika tidak memungkinkan, kenapa hal itu adalah melakukannya?WebClient
bisa meneruskan kredensial NTLM, tetapiHttpClient
tidak bisa. Saya dapat mencapai ini menggunakan penyamaran ASP.Net saja, dan tidak harus menggunakan Kerberos atau untuk menyimpan nama pengguna / kata sandi. Namun ini hanya bekerja denganWebClient
.OK, terima kasih untuk semua kontributor di atas. Saya menggunakan .NET 4.6 dan kami juga memiliki masalah yang sama. Saya menghabiskan waktu debugging
System.Net.Http
, khususnyaHttpClientHandler
, dan menemukan yang berikut:Jadi setelah menilai bahwa
ExecutionContext.IsFlowSuppressed()
mungkin itu penyebabnya, saya membungkus kode Peniruan sebagai berikut:Kode di dalam
SafeCaptureIdenity
(bukan kesalahan pengejaan saya), mengambilWindowsIdentity.Current()
identitas palsu kami. Ini sedang diambil karena kita sekarang menekan aliran. Karena menggunakan / membuang ini diatur ulang setelah doa.Sekarang tampaknya bekerja untuk kita, Fiuh!
sumber
using (System.Threading.ExecutionContext.SuppressFlow())
dan masalah ini diselesaikan untuk saya!NET Inti, saya berhasil mendapatkan
System.Net.Http.HttpClient
denganUseDefaultCredentials = true
melewati Windows kredensial pengguna dikonfirmasi untuk layanan back end dengan menggunakanWindowsIdentity.RunImpersonated
.sumber
Ini bekerja untuk saya setelah saya mengatur pengguna dengan akses internet di layanan Windows.
Dalam kode saya:
sumber
Ok jadi saya mengambil kode Joshoun dan membuatnya generik. Saya tidak yakin apakah saya harus menerapkan pola singleton pada kelas SynchronousPost. Mungkin seseorang yang lebih berpengetahuan bisa membantu.
Penerapan
// Aku menganggap kamu memiliki tipe betonmu sendiri. Dalam kasus saya, saya menggunakan kode terlebih dahulu dengan kelas bernama FileCategoryKelas Generik di sini. Anda dapat melewati semua jenis
Kelas Api ku terlihat seperti ini, jika kamu penasaran
Saya menggunakan ninject, dan pola repo dengan unit kerja. Bagaimanapun, kelas generik di atas sangat membantu.
sumber