ASP.NET: Session.SessionID เปลี่ยนระหว่างคำขอ


142

เหตุใดคุณสมบัติSessionIDบนSession -object ใน ASP.NET-page จึงเปลี่ยนไประหว่างการร้องขอ

ฉันมีหน้าดังนี้:

...
<div>
    SessionID: <%= SessionID %>
</div>
...

และเอาท์พุทที่เปลี่ยนแปลงตลอดเวลาที่ฉันกด F5 เป็นอิสระจากเบราว์เซอร์

คำตอบ:


225

นี่คือเหตุผล

เมื่อใช้สถานะเซสชันที่ใช้คุกกี้ 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;
}

23
ฉันไม่ทราบว่าไม่เคยมีปัญหากับมัน แต่ที่น่าสนใจที่จะรู้
Pharabus

1
@Cladudio คุณสามารถใส่รหัสหนึ่งบรรทัดแล้วคำตอบของคุณก็สมบูรณ์แบบ ข้อมูลที่น่าสนใจออกมาจากคำถามที่น่าสนใจ ... บวกไหม ;)
Seb Nilsson

2
ที่น่าสนใจก็คือการแก้ไขปัญหาของฉัน - แต่ปัญหานี้ประจักษ์เองหลังจากใช้รหัสฐานประมาณ 6 เดือนโดยไม่มีปัญหา ฉันไม่สามารถคิดด้วยเหตุผลใด ๆ ว่าทำไมถึงมีการเปลี่ยนแปลงอย่างกะทันหัน - ทุกคนสามารถแนะนำเหตุผลที่ sessionid จะได้รับการตั้งค่าใหม่เมื่อมันไม่ได้มาก่อนหรือไม่
หมู่ที่

2
@KumarHarsh: เมื่อคุณจัดเก็บวัตถุใด ๆ ในเซสชันรหัสเซสชันจะถูกแก้ไข นั่นคือสิ่งที่ฉันต้องการจะพูดด้วย "เว้นแต่คุณจะเข้าถึงวัตถุเซสชันของคุณในแบ็กเอนด์ ... " เมื่อคุณกำหนดsomeidเซสชันถ้าจะยังคงเหมือนเดิม พิจารณาว่าคำตอบนี้มีอายุมากกว่า 4 ปีไม่แน่ใจว่ามีการดัดแปลงใด ๆ ที่เกี่ยวข้องกับเรื่องนี้หรือไม่
Claudio Redi

9
ฉันสังเกตเห็นว่าเพียงเพิ่มวิธี Session_Start โดยที่ไม่มีอะไรใน Global.asax ของฉันก็สามารถใช้งานได้ ขอบคุณ @Claudio สำหรับเคล็ดลับแม้ว่า
Pedro

92

มีอีกเหตุผลที่ร้ายกาจกว่าสาเหตุที่สิ่งนี้อาจเกิดขึ้นแม้ว่าวัตถุเซสชันได้รับการเริ่มต้นตามที่แสดงโดย Cladudio

ใน Web.config หากมี<httpCookies>รายการที่ตั้งค่าไว้requireSSL="true"แต่คุณไม่ได้ใช้ HTTPS: สำหรับคำขอเฉพาะคุกกี้เซสชันจะไม่ถูกส่ง (หรืออาจจะไม่ถูกส่งคืนฉันไม่แน่ใจว่าอันไหน) ซึ่งหมายความว่า คุณจะพบกับเซสชันใหม่ล่าสุดสำหรับแต่ละคำขอ

ฉันพบวิธีนี้ยากใช้เวลาหลายชั่วโมงในการกลับไปมาระหว่างหลายคอมมิชชันในการควบคุมซอร์สของฉันจนกว่าฉันจะพบการเปลี่ยนแปลงเฉพาะที่ทำให้แอปพลิเคชันของฉันเสียหาย


5
ฉันรู้สิ่งนี้ แต่ก็ยังลืมมันทุก 3 เดือนหรือมากกว่านั้นและใช้เวลาสักสองสามชั่วโมงในการแก้จุดบกพร่อง ..
sotn

ในกรณีของฉันฉันกำลังทดสอบ localhost และ "requireSSL" ใน web.config ถูกตั้งค่าเป็น "true" ขอบคุณ
William Pereira

นี่เป็นกรณีของฉันและฉันใช้เวลามากเกินไปในการพยายามคิดออก (มีปลาเฮอริ่งแดงพร้อมไฟล์ web.config ที่แตกต่างกัน)
jmoreno

ข้อเสนอแนะของคุณด้านบนยังคงช่วยในปี 2561 นี่เป็นสถานการณ์ที่พบบ่อยที่สุด ขอบคุณ!
วีเจย์แบนซาล

5

ในกรณีของฉันฉันคิดออกว่าคุกกี้เซสชั่นมีโดเมนที่รวมคำนำหน้าในขณะที่ผมขอหน้าไม่มีwww. การเพิ่มURL นั้นแก้ไขปัญหาได้ทันที ต่อมาผมเปลี่ยนโดเมนคุกกี้จะถูกตั้งค่าให้แทนwww.
www..mysite.comwww.mysite.com


5

ปัญหาของฉันคือเรามีชุดนี้ใน web.config

<httpCookies httpOnlyCookies="true" requireSSL="true" />

ซึ่งหมายความว่าเมื่อทำการดีบักในที่ไม่ใช่ SSL (ค่าเริ่มต้น) คุกกี้รับรองความถูกต้องจะไม่ถูกส่งกลับไปยังเซิร์ฟเวอร์ นี่หมายความว่าเซิร์ฟเวอร์จะส่งคุกกี้รับรองความถูกต้องใหม่ (พร้อมเซสชันใหม่) สำหรับทุกคำขอกลับไปยังลูกค้า

การแก้ไขคือการตั้งค่า requiressl เป็นเท็จใน web.config และจริงใน web.release.config หรือเปิด SSL ในขณะที่การดีบัก:

เปิด SSL


สิ่งนี้แตกต่างจากคำตอบของ Neville Cook จากปี 2011 อย่างไร
Ian Kemp

4

ใช้คำตอบของเนวิลล์ (การลบ 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;
                }
            }
        }

2

ความเป็นไปได้อีกอย่างหนึ่งที่ทำให้ SessionID เปลี่ยนไประหว่างการร้องขอแม้เมื่อมีการกำหนด Session_OnStart และ / หรือการเริ่มต้นเซสชันนั้นก็คือชื่อโฮสต์ URL นั้นมีอักขระที่ไม่ถูกต้อง (เช่นขีดล่าง) ฉันเชื่อว่านี่เป็นเฉพาะ IE (ไม่ผ่านการตรวจสอบ) แต่ถ้า URL ของคุณคือบอกว่าhttp://server_name/appIE จะบล็อกคุกกี้ทั้งหมดและข้อมูลเซสชันของคุณจะไม่สามารถเข้าถึงได้ระหว่างคำขอ

ในความเป็นจริงคำขอแต่ละครั้งจะแยกเซสชันแยกต่างหากบนเซิร์ฟเวอร์ดังนั้นหากหน้าของคุณมีหลายภาพแท็กสคริปต์ ฯลฯ ดังนั้นคำขอ GET แต่ละรายการจะส่งผลให้เซสชันต่างกันบนเซิร์ฟเวอร์

ข้อมูลเพิ่มเติม: http://support.microsoft.com/kb/316112


2

ในกรณีของฉันสิ่งนี้กำลังเกิดขึ้นมากมายในสภาพแวดล้อมการพัฒนาและการทดสอบของฉัน หลังจากลองใช้วิธีแก้ปัญหาทั้งหมดข้างต้นโดยไม่ประสบความสำเร็จฉันพบว่าฉันสามารถแก้ไขปัญหานี้ได้ด้วยการลบคุกกี้เซสชันทั้งหมด ส่วนขยายนักพัฒนาเว็บทำให้ง่ายในการทำ ฉันใช้ Firefox เป็นส่วนใหญ่ในการทดสอบและพัฒนา แต่สิ่งนี้ก็เกิดขึ้นระหว่างการทดสอบใน Chrome การแก้ไขยังทำงานใน Chrome

ฉันยังไม่ได้ทำเช่นนี้ในสภาพแวดล้อมการผลิตและยังไม่ได้รับรายงานใด ๆ ของคนที่ไม่สามารถเข้าสู่ระบบได้สิ่งนี้ดูเหมือนจะเกิดขึ้นหลังจากการทำให้คุกกี้เซสชันปลอดภัยเท่านั้น มันไม่เคยเกิดขึ้นในอดีตเมื่อพวกเขาไม่ปลอดภัย


อัปเดต: สิ่งนี้จะเกิดขึ้นหลังจากเราเปลี่ยนคุกกี้เซสชันเท่านั้นเพื่อให้ปลอดภัย ฉันได้พิจารณาแล้วว่าปัญหาที่แน่นอนเกิดจากมีคุกกี้เซสชันสองรายการขึ้นไปในเบราว์เซอร์ที่มีเส้นทางและโดเมนเดียวกัน สิ่งที่เป็นปัญหาเสมอคือสิ่งที่มีค่าว่างหรือค่าว่าง หลังจากลบคุกกี้เฉพาะนั้นปัญหาได้รับการแก้ไข ฉันยังได้เพิ่มรหัสในวิธี Global.asax.cs Sessin_Start เพื่อตรวจสอบคุกกี้ที่ว่างเปล่านี้และหากตั้งค่าวันหมดอายุให้เป็นบางสิ่งในอดีต
Matt L

2

ในกรณีของฉันมันเป็นเพราะฉันกำลังแก้ไขเซสชันหลังจากเปลี่ยนเส้นทางจากเกตเวย์ในแอปพลิเคชันภายนอกดังนั้นเนื่องจากฉันใช้ IP แทน localhost ในหน้านั้นมันถือว่าเป็นเว็บไซต์อื่นที่มีเซสชันแตกต่างกัน

สรุป

ให้ความสนใจมากขึ้นถ้าคุณทำการดีบั๊กแอปพลิเคชันที่โฮสต์บน IIS แทน IIS express และผสมเครื่องของคุณhttp: // Ipและhttp: // localhostในหน้าต่างๆ


1

ปัญหาของฉันคือด้วยแอปพลิเคชัน Microsoft MediaRoom IPTV ปรากฎว่าแอปพลิเคชัน MPF MRML ไม่สนับสนุนคุกกี้ การเปลี่ยนไปใช้เซสชันที่ไม่มีเนื้อหาใน web.config แก้ปัญหาของฉันได้

<sessionState cookieless="true"  />

นี่เป็นบทความเก่าจริงๆเกี่ยวกับมัน: Cookieless ASP.NET


1

ฉันใช้. 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 };
        }
    }
}

ขอให้สังเกตว่าการเขียนและการอ่านเซสชันทำงานได้ แต่ดูเหมือนว่าจะไม่มีการส่งคุกกี้ไปยังเบราว์เซอร์ อย่างน้อยฉันก็ไม่พบส่วนหัว "ชุดคุกกี้" ที่ใดก็ได้


1

นี่เป็นการเปลี่ยนแปลงสำหรับฉันที่เริ่มต้นด้วย. NET 4.7.2 และเป็นเพราะคุณสมบัติ SameSite บนคุกกี้เซสชัน ดูที่นี่สำหรับข้อมูลเพิ่มเติม: https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

ค่าเริ่มต้นเปลี่ยนเป็น "หละหลวม" และเริ่มแบ่งสิ่งต่าง ๆ ฉันเปลี่ยนเป็น "ไม่มี" และสิ่งต่าง ๆ ทำงานตามที่คาดไว้


0

ตรวจสอบให้แน่ใจว่าคุณไม่มีการหมดเวลาของเซสชันที่สั้นมากและตรวจสอบให้แน่ใจว่าหากคุณใช้เซสชันที่อิงกับคุกกี้ที่คุณยอมรับเซสชัน

FireFox webDeveloperToolbar มีประโยชน์ในบางครั้งเช่นนี้คุณสามารถเห็นคุกกี้ที่ตั้งค่าไว้สำหรับแอปพลิเคชันของคุณ


2
ฉันเดาว่าการหมดเวลาเซสชันของฉันไม่ได้ถูกตั้งค่าไว้ต่ำกว่าหนึ่งวินาที มันเปลี่ยนไปทุกครั้งที่กด F5
Seb Nilsson

0

การรีเซ็ตรหัสเซสชันอาจมีหลายสาเหตุ อย่างไรก็ตามสิ่งที่กล่าวมาข้างต้นไม่เกี่ยวข้องกับปัญหาของฉัน ดังนั้นฉันจะอธิบายเพื่อใช้อ้างอิงในอนาคต

ในกรณีของฉันเซสชันใหม่ที่สร้างขึ้นในคำขอแต่ละครั้งทำให้เกิดลูปการเปลี่ยนเส้นทางแบบไม่สิ้นสุด การดำเนินการเปลี่ยนเส้นทางจะเกิดขึ้นในOnActionExecutingเหตุการณ์

และฉันได้ทำการล้างส่วนหัว http ทั้งหมด (เช่นเดียวกับในOnActionExecutingเหตุการณ์โดยใช้Response.ClearHeadersวิธี ) เพื่อป้องกันการแคชไซต์ทางฝั่งไคลเอ็นต์ แต่วิธีการนั้นจะล้างส่วนหัวทั้งหมดรวมถึงข้อมูลเกี่ยวกับเซสชันของผู้ใช้และข้อมูลทั้งหมดในการจัดเก็บชั่วคราว (ซึ่งฉันใช้ในโปรแกรมในภายหลัง) ดังนั้นแม้การตั้งค่าเซสชันใหม่ในเหตุการณ์ Session_Start ก็ไม่ได้ช่วยอะไร

เพื่อแก้ไขปัญหาของฉันฉันมั่นใจว่าจะไม่ลบส่วนหัวเมื่อมีการเปลี่ยนเส้นทางเกิดขึ้น

หวังว่าจะช่วยใครซักคน


0

ฉันพบปัญหานี้ในลักษณะที่แตกต่างออกไป คอนโทรลเลอร์ที่มีคุณสมบัตินี้[SessionState(SessionStateBehavior.ReadOnly)]กำลังอ่านจากเซสชันอื่นแม้ว่าฉันได้ตั้งค่าในเซสชันดั้งเดิมเมื่อเริ่มต้นแอป ฉันเพิ่มมูลค่าเซสชันผ่าน _layout.cshtml (อาจไม่ใช่แนวคิดที่ดีที่สุดใช่ไหม)

มันชัดเจนว่า ReadOnly ก่อให้เกิดปัญหาเพราะเมื่อฉันลบคุณลักษณะเซสชันเดิม (และ SessionId) จะยังคงอยู่ในชั้นเชิง การใช้โซลูชันของ Claudio / Microsoft แก้ไขปัญหานั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.