Saya memiliki masalah aneh dengan menggunakan otentikasi cookie Owin.
Ketika saya memulai otentikasi server IIS saya berfungsi dengan baik di IE / Firefox dan Chrome.
Saya mulai melakukan beberapa pengujian dengan Otentikasi dan masuk pada platform yang berbeda dan saya menemukan kesalahan yang aneh. Kerangka kerja Owin / IIS secara sporadis tidak mengirim cookie apa pun ke browser. Saya akan mengetikkan nama pengguna dan kata sandi yang benar ketika kode berjalan tetapi tidak ada cookie yang dikirim ke browser sama sekali. Jika saya me-restart server itu mulai berfungsi maka di beberapa titik saya akan mencoba masuk dan lagi cookie berhenti terkirim. Melangkah kode tidak melakukan apa-apa dan tidak ada kesalahan.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true,
AuthenticationType = "ABC",
LoginPath = new PathString("/Account/Login"),
CookiePath = "/",
CookieName = "ABC",
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = ctx =>
{
if (!IsAjaxRequest(ctx.Request))
{
ctx.Response.Redirect(ctx.RedirectUri);
}
}
}
});
Dan dalam prosedur login saya, saya memiliki kode berikut:
IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var authentication = HttpContext.Current.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("ABC");
identity.AddClaim(new Claim(ClaimTypes.Name, user.Username));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.User_ID.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Role, role.myRole.ToString()));
authentication.AuthenticationResponseGrant =
new AuthenticationResponseGrant(identity, new AuthenticationProperties()
{
IsPersistent = isPersistent
});
authenticationManager.SignIn(new AuthenticationProperties() {IsPersistent = isPersistent}, identity);
Pembaruan 1: Tampaknya salah satu penyebab masalah adalah ketika saya menambahkan item ke sesi masalah dimulai. Menambahkan sesuatu yang sederhana seperti Session.Content["ABC"]= 123
tampaknya menciptakan masalah.
Yang dapat saya lakukan adalah sebagai berikut: 1) (Chrome) Ketika saya masuk saya mendapatkan ASP.NET_SessionId + cookie otentikasi saya. 2) Saya pergi ke halaman yang menetapkan session.contents ... 3) Buka browser baru (Firefox) dan coba masuk dan tidak menerima ASP.NET_SessionId juga tidak mendapatkan Cookie Otentikasi 4) Sementara browser pertama memiliki ASP.NET_SessionId terus berfungsi. Begitu saya menghapus cookie ini, ia memiliki masalah yang sama dengan semua browser lain yang sedang saya kerjakan pada alamat ip (10.xxx) dan localhost.
Pembaruan 2: Memaksa pembuatan ASPNET_SessionId
pertama pada halaman login_load saya sebelum otentikasi dengan OWIN.
1) sebelum saya mengautentikasi dengan OWIN, saya membuat Session.Content
nilai acak pada halaman login saya untuk memulai ASP.NET_SessionId 2) kemudian saya mengautentikasi dan membuat sesi lebih lanjut 3) Browser lain tampaknya sekarang berfungsi
Ini aneh. Saya hanya dapat menyimpulkan bahwa ini ada hubungannya dengan ASP dan OWIN berpikir mereka berada di domain yang berbeda atau sesuatu seperti itu.
Perbarui 3 - Perilaku aneh antara keduanya.
Identifikasi perilaku aneh tambahan - Batas waktu sesi Owin dan ASP berbeda. Apa yang saya lihat adalah bahwa sesi Owin saya tetap hidup lebih lama dari sesi ASP saya melalui beberapa mekanisme. Jadi ketika masuk: 1.) Saya memiliki sesi auth berbasis cookie 2.) Saya menetapkan beberapa variabel sesi
Variabel sesi saya (2) "mati" sebelum variabel sesi cookie owin memaksa login ulang, yang menyebabkan perilaku tak terduga di seluruh aplikasi saya. (Orang masuk tetapi tidak benar-benar masuk)
Perbarui 3B
Setelah beberapa penggalian, saya melihat beberapa komentar pada halaman yang mengatakan batas waktu otentikasi "formulir" dan batas waktu sesi harus cocok. Saya pikir biasanya keduanya sinkron tetapi karena alasan apa pun keduanya tidak sinkron.
Ringkasan Penanganan Masalah
1) Selalu buat Sesi terlebih dahulu sebelum otentikasi. Pada dasarnya buat sesi ketika Anda memulai aplikasiSession["Workaround"] = 0;
2) [Eksperimental] jika Anda bertahan dengan cookie, pastikan batas waktu / panjang OWIN Anda lebih lama dari sessionTimeout Anda di web.config Anda (dalam pengujian)
sumber
Jawaban:
Saya telah mengalami masalah yang sama dan menelusuri penyebabnya untuk implementasi hosting OWIN ASP.NET. Saya akan mengatakan itu bug.
Beberapa latar belakang
Temuan saya didasarkan pada versi perakitan ini:
OWIN menggunakan abstraksinya sendiri untuk bekerja dengan Cookie tanggapan ( Microsoft.Owin.ResponseCookieCollection ). Implementasi ini secara langsung membungkus koleksi tajuk respons dan karenanya memperbarui tajuk Set-Cookie . OWIN ASP.NET host ( Microsoft.Owin.Host.SystemWeb ) baru saja membungkus System.Web.HttpResponse dan koleksi tajuknya . Jadi ketika cookie baru dibuat melalui OWIN, header Set-Cookie response diubah secara langsung.
Tetapi ASP.NET juga menggunakan abstraksi itu sendiri untuk bekerja dengan Cookie tanggapan. Ini dihadapkan kepada kami sebagai properti System.Web.HttpResponse.Cookies dan diimplementasikan oleh System.Web.HttpCookieCollection kelas tertutup . Implementasi ini tidak membungkus header Set-Cookie respons secara langsung tetapi menggunakan beberapa optimisasi dan beberapa notifikasi internal untuk mewujudkannya diubah menjadi objek respons.
Lalu ada titik keterlambatan dalam permintaan seumur hidup di mana HttpCookieCollection berubah status diuji ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ) dan cookie diserialisasi ke header Set-Cookie . Jika koleksi ini dalam keadaan tertentu, seluruh tajuk Set-Cookie pertama kali dihapus dan dibuat ulang dari cookie yang disimpan dalam koleksi.
Implementasi sesi ASP.NET menggunakan properti System.Web.HttpResponse.Cookies untuk menyimpan cookie ASP.NET_SessionId itu. Juga ada beberapa optimasi dasar dalam modul state sesi ASP.NET ( System.Web.SessionState.SessionStateModule ) diimplementasikan melalui properti statis bernama s_sessionEverSet yang cukup jelas. Jika Anda pernah menyimpan sesuatu ke keadaan sesi di aplikasi Anda, modul ini akan melakukan sedikit lebih banyak pekerjaan untuk setiap permintaan.
Kembali ke masalah login kita
Dengan semua bagian ini, skenario Anda dapat dijelaskan.
Kasus 1 - Sesi tidak pernah ditetapkan
Properti System.Web.SessionState.SessionStateModule , s_sessionEverSet salah. Tidak ada id sesi yang dihasilkan oleh modul status sesi dan status pengumpulan System.Web.HttpResponse.Cookies tidak terdeteksi saat diubah . Dalam hal ini, cookie OWIN dikirim dengan benar ke browser dan pekerjaan login.
Kasus 2 - Sesi digunakan di suatu tempat dalam aplikasi, tetapi tidak sebelum pengguna mencoba untuk mengotentikasi
Properti System.Web.SessionState.SessionStateModule , s_sessionEverSet benar. Session Id dihasilkan oleh SessionStateModule , ASP.NET_SessionId ditambahkan ke koleksi System.Web.HttpResponse.Cookies tetapi dihapus kemudian dalam permintaan seumur hidup karena sesi pengguna sebenarnya kosong. Dalam hal ini, kondisi pengumpulan System.Web.HttpResponse.Cookies terdeteksi sebagai diubah dan header Set-Cookie pertama kali dihapus sebelum cookie diserialisasi ke nilai header.
Dalam hal ini, cookie respons OWIN "hilang" dan pengguna tidak diautentikasi dan dialihkan kembali ke halaman masuk.
Kasus 3 - Sesi digunakan sebelum pengguna mencoba untuk mengotentikasi
Properti System.Web.SessionState.SessionStateModule , s_sessionEverSet benar. Id Session dihasilkan oleh SessionStateModule , ASP.NET_SessionId ditambahkan ke System.Web.HttpResponse.Cookies . Karena pengoptimalan internal di System.Web.HttpCookieCollection dan System.Web.HttpResponse.GenerateResponseHeadersForCookies () Header Set-Cookie TIDAK pertama kali dihapus tetapi hanya diperbarui.
Dalam hal ini, cookie autentikasi OWIN dan cookie ASP.NET_SessionId dikirim sebagai respons dan proses masuk.
Masalah yang lebih umum dengan cookie
Seperti yang Anda lihat masalahnya lebih umum dan tidak terbatas pada sesi ASP.NET. Jika Anda meng-hosting OWIN melalui Microsoft.Owin.Host.SystemWeb dan Anda / sesuatu langsung menggunakan System.Web.HttpResponse.Cookies koleksi Anda berisiko.
Misalnya ini berfungsi dan kedua cookie dikirim dengan benar ke browser ...
Tapi ini tidak dan OwinCookie "hilang" ...
Keduanya diuji dari VS2013, IISExpress dan template proyek MVC default.
sumber
Dimulai dengan analisis hebat oleh @TomasDolezal, saya telah melihat sumber Owin dan System.Web.
Masalahnya adalah bahwa System.Web memiliki sumber utama informasi cookie dan itu bukan header Set-Cookie. Owin hanya tahu tentang header Set-Cookie. Solusinya adalah memastikan bahwa cookie apa pun yang ditetapkan oleh Owin juga ditetapkan dalam
HttpContext.Current.Response.Cookies
koleksi.Saya telah membuat middleware kecil ( sumber , nuget ) yang melakukan hal itu, yang dimaksudkan untuk ditempatkan tepat di atas registrasi cookie middleware.
sumber
app.UseKentorCookieMiddlewareSaver();
di Startup.Auth.cs. Ini juga harus menangani pembersihan cookie logout.app.UseKentorOwinCookieSaver()
dan mungkin termasuk dalam Anda jawaban asli seperti pada halaman GitHub paket .Singkatnya, manajer .NET cookie akan memenangkan manajer cookie OWIN dan menimpa cookie yang ditetapkan pada layer OWIN . Cara mengatasinya adalah dengan menggunakan kelas SystemWebCookieManager, yang disediakan sebagai solusi pada Proyek Katana di sini . Anda perlu menggunakan kelas ini atau yang serupa dengannya, yang akan memaksa OWIN untuk menggunakan .NET cookie manager sehingga tidak ada inkonsistensi :
Di startup aplikasi Anda, tetapkan saja ketika Anda membuat dependensi OWIN Anda:
Jawaban serupa telah diberikan di sini tetapi tidak mencakup semua basis kode yang diperlukan untuk menyelesaikan masalah, jadi saya melihat perlunya menambahkannya di sini karena tautan eksternal ke Proyek Katana mungkin turun dan ini harus sepenuhnya dicatat sebagai solusi di sini juga.
sumber
ASP.NET Webforms, OWIN, ADFS
Startup.ConfigureAuth
kita milikiapp.UseCookieAuthentication
danapp.UseWsFederationAuthentication
akhirnyaapp.UseStageMarker
Tim Katana menjawab masalah yang diangkat Tomas Dolezar, dan memposting dokumentasi tentang pemecahan masalah :
Lihat implementasi SystemWebCookieManager dari dokumentasi (tautan di atas)
Informasi lebih lanjut di sini
Edit
Di bawah langkah-langkah yang kami ambil untuk menyelesaikan masalah. 1. dan 2. menyelesaikan masalah secara terpisah tetapi kami memutuskan untuk menerapkan keduanya hanya dalam kasus:
1. Gunakan SystemWebCookieManager
2. Setel variabel sesi:
(catatan: metode Inisialisasi di atas adalah tempat logis untuk perbaikan karena basis. Menginisialisasi membuat Sesi tersedia. Namun, perbaikan juga dapat diterapkan kemudian karena di OpenId pertama ada permintaan anonim, kemudian redirect ke penyedia OpenId dan kemudian kembali ke aplikasi. Masalahnya akan terjadi setelah pengalihan kembali ke aplikasi sementara perbaikan menetapkan variabel sesi sudah selama permintaan anonim pertama sehingga memperbaiki masalah sebelum terjadi pengalihan kembali bahkan terjadi)
Edit 2
Copy-paste dari proyek Katana 2016-05-14:
Tambahkan ini:
...dan ini:
sumber
ControllerContext.HttpContext.Session.RemoveAll();
dalamExternalLogin()
tindakan Anda , sebelum meneleponChallengeResult()
. Saya tidak tahu apakah itu solusi terbaik, tetapi ini adalah yang paling sederhana.?.
(operator null-kondisional) hanya berfungsi di C # 6.Jawaban sudah disediakan, tetapi di owin 3.1.0, ada kelas SystemWebChunkingCookieManager yang dapat digunakan.
https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs
https://raw.githubusercontent.com/aspnet/AspNetKatana/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs
sumber
Jika Anda mengatur cookie di middleware OWIN sendiri, kemudian menggunakan
OnSendingHeaders
tampaknya untuk menyelesaikan masalah.Misalnya, menggunakan kode di bawah
owinResponseCookie2
ini akan ditetapkan, meskipunowinResponseCookie1
tidak:sumber
Saya menghadapi Masalah Sejenis dengan Visual Studio 2017 dan .net MVC 5.2.4 , Memperbarui Nuget Microsoft.Owin.Security.Google ke versi terbaru yang saat ini 4.0.1 bekerja untuk saya! Semoga ini Membantu seseorang!
sumber
Solusi kode satu baris tercepat:
Cukup tambahkan baris ini sebelum metode CreateIdentity:
sumber
HttpContext.Current.Session["RunSession"] = "1";
? di Globa.asaxSession_Start
?Saya memiliki gejala yang sama dengan tajuk Set-Cookie yang tidak dikirim tetapi tidak ada jawaban yang membantu saya. Semuanya bekerja pada mesin lokal saya tetapi ketika digunakan untuk produksi header cookie tidak akan pernah bisa ditetapkan.
Ternyata itu kombinasi menggunakan kustom
CookieAuthenticationMiddleware
dengan WebApi bersama dengan dukungan kompresi WebApiUntungnya saya menggunakan ELMAH dalam proyek saya yang memungkinkan saya untuk pengecualian ini dicatat:
Yang membawa saya ke Masalah GitHub ini
Pada dasarnya, jika Anda memiliki pengaturan aneh seperti milik saya, Anda ingin menonaktifkan kompresi untuk pengontrol / metode WebApi Anda yang mengatur cookie, atau coba
OwinServerCompressionHandler
.sumber