เหตุใดคุณสมบัติSessionIDบนSession -object ใน ASP.NET-page จึงเปลี่ยนไประหว่างการร้องขอ
ฉันมีหน้าดังนี้:
...
<div>
SessionID: <%= SessionID %>
</div>
...
และเอาท์พุทที่เปลี่ยนแปลงตลอดเวลาที่ฉันกด F5 เป็นอิสระจากเบราว์เซอร์
เหตุใดคุณสมบัติSessionIDบนSession -object ใน ASP.NET-page จึงเปลี่ยนไประหว่างการร้องขอ
ฉันมีหน้าดังนี้:
...
<div>
SessionID: <%= SessionID %>
</div>
...
และเอาท์พุทที่เปลี่ยนแปลงตลอดเวลาที่ฉันกด F5 เป็นอิสระจากเบราว์เซอร์
คำตอบ:
นี่คือเหตุผล
เมื่อใช้สถานะเซสชันที่ใช้คุกกี้ ASP.NET จะไม่จัดสรรหน่วยเก็บสำหรับข้อมูลเซสชันจนกว่าจะใช้วัตถุเซสชัน ดังนั้นรหัสเซสชันใหม่จะถูกสร้างขึ้นสำหรับคำขอแต่ละหน้าจนกว่าจะมีการเข้าถึงวัตถุเซสชัน หากแอปพลิเคชันของคุณต้องการ ID เซสชันแบบคงที่สำหรับทั้งเซสชันคุณสามารถใช้วิธี Session_Start ในไฟล์ Global.asax ของแอปพลิเคชันและเก็บข้อมูลในวัตถุเซสชันเพื่อแก้ไขรหัสเซสชันหรือคุณสามารถใช้รหัสในส่วนอื่นของคุณ แอปพลิเคชันเพื่อเก็บข้อมูลอย่างชัดเจนในวัตถุเซสชัน
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx
ดังนั้นโดยทั่วไปถ้าคุณเข้าถึงวัตถุเซสชันของคุณในแบ็กเอนด์จะมีการสร้าง sessionId ใหม่กับคำขอแต่ละครั้ง
แก้ไข
ต้องเพิ่มรหัสนี้ในไฟล์ Global.asax มันเพิ่มรายการในวัตถุเซสชันเพื่อให้คุณแก้ไขเซสชันจนกว่าจะหมดอายุ
protected void Session_Start(Object sender, EventArgs e)
{
Session["init"] = 0;
}
someid
เซสชันถ้าจะยังคงเหมือนเดิม พิจารณาว่าคำตอบนี้มีอายุมากกว่า 4 ปีไม่แน่ใจว่ามีการดัดแปลงใด ๆ ที่เกี่ยวข้องกับเรื่องนี้หรือไม่
มีอีกเหตุผลที่ร้ายกาจกว่าสาเหตุที่สิ่งนี้อาจเกิดขึ้นแม้ว่าวัตถุเซสชันได้รับการเริ่มต้นตามที่แสดงโดย Cladudio
ใน Web.config หากมี<httpCookies>
รายการที่ตั้งค่าไว้requireSSL="true"
แต่คุณไม่ได้ใช้ HTTPS: สำหรับคำขอเฉพาะคุกกี้เซสชันจะไม่ถูกส่ง (หรืออาจจะไม่ถูกส่งคืนฉันไม่แน่ใจว่าอันไหน) ซึ่งหมายความว่า คุณจะพบกับเซสชันใหม่ล่าสุดสำหรับแต่ละคำขอ
ฉันพบวิธีนี้ยากใช้เวลาหลายชั่วโมงในการกลับไปมาระหว่างหลายคอมมิชชันในการควบคุมซอร์สของฉันจนกว่าฉันจะพบการเปลี่ยนแปลงเฉพาะที่ทำให้แอปพลิเคชันของฉันเสียหาย
ในกรณีของฉันฉันคิดออกว่าคุกกี้เซสชั่นมีโดเมนที่รวมคำนำหน้าในขณะที่ผมขอหน้าไม่มีwww.
การเพิ่มURL นั้นแก้ไขปัญหาได้ทันที ต่อมาผมเปลี่ยนโดเมนคุกกี้จะถูกตั้งค่าให้แทนwww.
www.
.mysite.com
www.mysite.com
ปัญหาของฉันคือเรามีชุดนี้ใน web.config
<httpCookies httpOnlyCookies="true" requireSSL="true" />
ซึ่งหมายความว่าเมื่อทำการดีบักในที่ไม่ใช่ SSL (ค่าเริ่มต้น) คุกกี้รับรองความถูกต้องจะไม่ถูกส่งกลับไปยังเซิร์ฟเวอร์ นี่หมายความว่าเซิร์ฟเวอร์จะส่งคุกกี้รับรองความถูกต้องใหม่ (พร้อมเซสชันใหม่) สำหรับทุกคำขอกลับไปยังลูกค้า
การแก้ไขคือการตั้งค่า requiressl เป็นเท็จใน web.config และจริงใน web.release.config หรือเปิด SSL ในขณะที่การดีบัก:
ใช้คำตอบของเนวิลล์ (การลบ requireSSL = true ใน web.config) และปรับเปลี่ยนรหัสของ Joel Etherton เล็กน้อยนี่คือรหัสที่ควรจัดการกับไซต์ที่ทำงานทั้งในโหมด SSL และไม่ใช่โหมด SSL ขึ้นอยู่กับผู้ใช้และหน้าเว็บ (ฉัน ฉันกำลังย้อนกลับไปสู่โค้ดและยังไม่ได้ทดสอบกับ SSL แต่คาดว่ามันจะทำงานได้ - จะไม่ว่างในภายหลังเพื่อกลับมาที่นี่ดังนั้นนี่คือ:
if (HttpContext.Current.Response.Cookies.Count > 0)
{
foreach (string s in HttpContext.Current.Response.Cookies.AllKeys)
{
if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
{
HttpContext.Current.Response.Cookies[s].Secure = HttpContext.Current.Request.IsSecureConnection;
}
}
}
ความเป็นไปได้อีกอย่างหนึ่งที่ทำให้ SessionID เปลี่ยนไประหว่างการร้องขอแม้เมื่อมีการกำหนด Session_OnStart และ / หรือการเริ่มต้นเซสชันนั้นก็คือชื่อโฮสต์ URL นั้นมีอักขระที่ไม่ถูกต้อง (เช่นขีดล่าง) ฉันเชื่อว่านี่เป็นเฉพาะ IE (ไม่ผ่านการตรวจสอบ) แต่ถ้า URL ของคุณคือบอกว่าhttp://server_name/app
IE จะบล็อกคุกกี้ทั้งหมดและข้อมูลเซสชันของคุณจะไม่สามารถเข้าถึงได้ระหว่างคำขอ
ในความเป็นจริงคำขอแต่ละครั้งจะแยกเซสชันแยกต่างหากบนเซิร์ฟเวอร์ดังนั้นหากหน้าของคุณมีหลายภาพแท็กสคริปต์ ฯลฯ ดังนั้นคำขอ GET แต่ละรายการจะส่งผลให้เซสชันต่างกันบนเซิร์ฟเวอร์
ข้อมูลเพิ่มเติม: http://support.microsoft.com/kb/316112
ในกรณีของฉันสิ่งนี้กำลังเกิดขึ้นมากมายในสภาพแวดล้อมการพัฒนาและการทดสอบของฉัน หลังจากลองใช้วิธีแก้ปัญหาทั้งหมดข้างต้นโดยไม่ประสบความสำเร็จฉันพบว่าฉันสามารถแก้ไขปัญหานี้ได้ด้วยการลบคุกกี้เซสชันทั้งหมด ส่วนขยายนักพัฒนาเว็บทำให้ง่ายในการทำ ฉันใช้ Firefox เป็นส่วนใหญ่ในการทดสอบและพัฒนา แต่สิ่งนี้ก็เกิดขึ้นระหว่างการทดสอบใน Chrome การแก้ไขยังทำงานใน Chrome
ฉันยังไม่ได้ทำเช่นนี้ในสภาพแวดล้อมการผลิตและยังไม่ได้รับรายงานใด ๆ ของคนที่ไม่สามารถเข้าสู่ระบบได้สิ่งนี้ดูเหมือนจะเกิดขึ้นหลังจากการทำให้คุกกี้เซสชันปลอดภัยเท่านั้น มันไม่เคยเกิดขึ้นในอดีตเมื่อพวกเขาไม่ปลอดภัย
ในกรณีของฉันมันเป็นเพราะฉันกำลังแก้ไขเซสชันหลังจากเปลี่ยนเส้นทางจากเกตเวย์ในแอปพลิเคชันภายนอกดังนั้นเนื่องจากฉันใช้ IP แทน localhost ในหน้านั้นมันถือว่าเป็นเว็บไซต์อื่นที่มีเซสชันแตกต่างกัน
สรุป
ให้ความสนใจมากขึ้นถ้าคุณทำการดีบั๊กแอปพลิเคชันที่โฮสต์บน IIS แทน IIS express และผสมเครื่องของคุณhttp: // Ipและhttp: // localhostในหน้าต่างๆ
ปัญหาของฉันคือด้วยแอปพลิเคชัน Microsoft MediaRoom IPTV ปรากฎว่าแอปพลิเคชัน MPF MRML ไม่สนับสนุนคุกกี้ การเปลี่ยนไปใช้เซสชันที่ไม่มีเนื้อหาใน web.config แก้ปัญหาของฉันได้
<sessionState cookieless="true" />
นี่เป็นบทความเก่าจริงๆเกี่ยวกับมัน: Cookieless ASP.NET
ฉันใช้. NET Core 2.1 และฉันทราบดีว่าคำถามนั้นไม่เกี่ยวกับ Core แต่อินเทอร์เน็ตขาดหายไปและ Google ก็พาฉันมาที่นี่ดังนั้นหวังว่าจะช่วยชีวิตผู้อื่นได้ไม่กี่ชั่วโมง
Startup.cs
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder
.WithOrigins("http://localhost:3000") // important
.AllowCredentials() // important
.AllowAnyMethod()
.AllowAnyHeader(); // obviously just for testing
}));
client.js
const resp = await fetch("https://localhost:5001/api/user", {
method: 'POST',
credentials: 'include', // important
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
Controllers/LoginController.cs
namespace WebServer.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
[HttpPost]
public IEnumerable<string> Post([FromBody]LoginForm lf)
{
string prevUsername = HttpContext.Session.GetString("username");
Console.WriteLine("Previous username: " + prevUsername);
HttpContext.Session.SetString("username", lf.username);
return new string[] { lf.username, lf.password };
}
}
}
ขอให้สังเกตว่าการเขียนและการอ่านเซสชันทำงานได้ แต่ดูเหมือนว่าจะไม่มีการส่งคุกกี้ไปยังเบราว์เซอร์ อย่างน้อยฉันก็ไม่พบส่วนหัว "ชุดคุกกี้" ที่ใดก็ได้
นี่เป็นการเปลี่ยนแปลงสำหรับฉันที่เริ่มต้นด้วย. NET 4.7.2 และเป็นเพราะคุณสมบัติ SameSite บนคุกกี้เซสชัน ดูที่นี่สำหรับข้อมูลเพิ่มเติม: https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
ค่าเริ่มต้นเปลี่ยนเป็น "หละหลวม" และเริ่มแบ่งสิ่งต่าง ๆ ฉันเปลี่ยนเป็น "ไม่มี" และสิ่งต่าง ๆ ทำงานตามที่คาดไว้
ตรวจสอบให้แน่ใจว่าคุณไม่มีการหมดเวลาของเซสชันที่สั้นมากและตรวจสอบให้แน่ใจว่าหากคุณใช้เซสชันที่อิงกับคุกกี้ที่คุณยอมรับเซสชัน
FireFox webDeveloperToolbar มีประโยชน์ในบางครั้งเช่นนี้คุณสามารถเห็นคุกกี้ที่ตั้งค่าไว้สำหรับแอปพลิเคชันของคุณ
การรีเซ็ตรหัสเซสชันอาจมีหลายสาเหตุ อย่างไรก็ตามสิ่งที่กล่าวมาข้างต้นไม่เกี่ยวข้องกับปัญหาของฉัน ดังนั้นฉันจะอธิบายเพื่อใช้อ้างอิงในอนาคต
ในกรณีของฉันเซสชันใหม่ที่สร้างขึ้นในคำขอแต่ละครั้งทำให้เกิดลูปการเปลี่ยนเส้นทางแบบไม่สิ้นสุด การดำเนินการเปลี่ยนเส้นทางจะเกิดขึ้นในOnActionExecutingเหตุการณ์
และฉันได้ทำการล้างส่วนหัว http ทั้งหมด (เช่นเดียวกับในOnActionExecutingเหตุการณ์โดยใช้Response.ClearHeadersวิธี ) เพื่อป้องกันการแคชไซต์ทางฝั่งไคลเอ็นต์ แต่วิธีการนั้นจะล้างส่วนหัวทั้งหมดรวมถึงข้อมูลเกี่ยวกับเซสชันของผู้ใช้และข้อมูลทั้งหมดในการจัดเก็บชั่วคราว (ซึ่งฉันใช้ในโปรแกรมในภายหลัง) ดังนั้นแม้การตั้งค่าเซสชันใหม่ในเหตุการณ์ Session_Start ก็ไม่ได้ช่วยอะไร
เพื่อแก้ไขปัญหาของฉันฉันมั่นใจว่าจะไม่ลบส่วนหัวเมื่อมีการเปลี่ยนเส้นทางเกิดขึ้น
หวังว่าจะช่วยใครซักคน
ฉันพบปัญหานี้ในลักษณะที่แตกต่างออกไป คอนโทรลเลอร์ที่มีคุณสมบัตินี้[SessionState(SessionStateBehavior.ReadOnly)]
กำลังอ่านจากเซสชันอื่นแม้ว่าฉันได้ตั้งค่าในเซสชันดั้งเดิมเมื่อเริ่มต้นแอป ฉันเพิ่มมูลค่าเซสชันผ่าน _layout.cshtml (อาจไม่ใช่แนวคิดที่ดีที่สุดใช่ไหม)
มันชัดเจนว่า ReadOnly ก่อให้เกิดปัญหาเพราะเมื่อฉันลบคุณลักษณะเซสชันเดิม (และ SessionId) จะยังคงอยู่ในชั้นเชิง การใช้โซลูชันของ Claudio / Microsoft แก้ไขปัญหานั้น