จะจัดการคุกกี้หลายตัวที่มีชื่อเดียวกันได้อย่างไร?


92

ตัวอย่างเช่นฉันมีแอปพลิเคชันที่ส่งส่วนหัว HTTP ต่อไปนี้เพื่อตั้งค่าเป็นคุกกี้ชื่อ "a":

Set-Cookie: a=1;Path=/;Version=1
Set-Cookie: a=2;Path=/example;Version=1

หากฉันเข้าถึง/exampleเซิร์ฟเวอร์ทั้งสองเส้นทางถูกต้องดังนั้นฉันจึงมีคุกกี้สองตัวที่ชื่อว่า "a"! เนื่องจากเบราว์เซอร์ไม่ได้ส่งข้อมูลเส้นทางใด ๆ จึงไม่สามารถแยกแยะคุกกี้ทั้งสองได้

Cookie: a=2; a=1

กรณีนี้ควรจัดการอย่างไร? เลือกอันแรกไหม สร้างรายการที่มีค่าคุกกี้ทั้งหมดหรือไม่ หรือกรณีดังกล่าวควรถือเป็นความผิดพลาดของผู้พัฒนา?


ฉันจะทำให้ดีที่สุด (อ่าน: ทุกอย่างที่ทำได้) เพื่อหลีกเลี่ยงชื่อคุกกี้ที่ซ้ำกัน คนส่วนใหญ่ไม่เคยพบปัญหานี้ - ด้วยเหตุผลที่ดี

เว็บไซต์สามารถอ่านคุกกี้ของตัวเองเท่านั้น ไม่สามารถอ่านคุกกี้ของเว็บไซต์ / โดเมนอื่นได้ ความปลอดภัยนี้ได้รับการรับรองโดยเบราว์เซอร์ นี่อาจเป็นเคล็ดลับสำหรับผู้เริ่มต้นอย่างแท้จริง (ฉันมีความสับสน)
อรุณ

คำตอบ:


38

จากบทความนี้ใน SitePoint :

หากคุกกี้หลายชื่อที่มีชื่อเดียวกันตรงกับ URI คำขอที่กำหนดเบราว์เซอร์จะเลือกคุกกี้

ยิ่งเส้นทางเฉพาะเจาะจงมากเท่าใดความสำคัญก็ยิ่งสูงขึ้นเท่านั้น อย่างไรก็ตามความสำคัญตามแอตทริบิวต์อื่น ๆ รวมถึงโดเมนนั้นไม่ได้ระบุไว้และอาจแตกต่างกันไปในแต่ละเบราว์เซอร์ ซึ่งหมายความว่าหากคุณตั้งค่าคุกกี้ที่มีชื่อเดียวกันกับ“ .example.org” และ“ www.example.org” คุณจะไม่แน่ใจว่าคุกกี้ใดจะถูกส่งกลับ

แก้ไข: ข้อมูลนี้จากปี 2010 ดูเหมือนจะล้าสมัยดูเหมือนว่าเบราว์เซอร์สามารถส่งคุกกี้หลายรายการในทางกลับกันได้โปรดดูคำตอบโดย @Nate ด้านล่างสำหรับรายละเอียด


9
แล้วเราจะลบคุกกี้ที่เหมือนกันหลาย ๆ อันได้อย่างไร? ฉันใช้เวลาสองวันแล้วและคุกกี้ที่ซ้ำกันดูเหมือนจะไม่สามารถทำลายได้
Bob Jones

13
@ แบรนต์บทความนั้นอาจไม่ถูกต้องเล็กน้อย - ฉันเพิ่งเห็น Chrome ส่งคุกกี้สองตัวที่มีชื่อเดียวกัน (แต่คนละเส้นทาง) กลับมาดังนั้น "เบราว์เซอร์เลือก" จึงไม่จำเป็นต้องเป็นจริง คุกกี้เส้นทางที่ลึกที่สุดถูกส่งไปก่อน BTW ซึ่งดูสมเหตุสมผล และคุกกี้อีกชิ้นก็อยู่ระหว่างนั้นด้วย
Jonas N

3
Firefox (15) ยังส่งคุกกี้สองตัวที่มีชื่อเดียวกัน! หากพบกับคุกกี้สองรายการสำหรับโดเมน.a.comและโฮสต์a.com
Taha Jahangir

อันที่จริงข้อมูลนี้ไม่ถูกต้อง คำตอบของ @Nate ควรทำเครื่องหมายว่าถูกต้อง
Dan Milon

5
404: ไม่พบคำตอบของ @ Nate ที่มีชื่อเสียง
d.popov

90

คำตอบที่อ้างถึงบทความใน SitePoint ยังไม่สมบูรณ์ทั้งหมด โปรดดูRFC 6265 (เพื่อความเป็นธรรม RFC นี้เปิดตัวในปี 2011 หลังจากที่โพสต์คำถามนี้ซึ่งแทนที่RFC 2965ก่อนหน้าจากปี 2000 และRFC 2109จากปี 1997)

ส่วน5.4ส่วนย่อยที่ 2 มีไว้เพื่อบอกว่า:

ตัวแทนผู้ใช้ควรจัดเรียงรายการคุกกี้ตามลำดับต่อไปนี้:

  • คุกกี้ที่มีเส้นทางยาวกว่าจะแสดงรายการก่อนคุกกี้ที่มีเส้นทางสั้นกว่า

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

นอกจากนี้ยังมีอัญมณีชิ้นเล็ก ๆ นี้ในหัวข้อ4.2.2 :

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

ในตัวอย่างคำขอคุกกี้ของคุณ ( คุกกี้: a = 2; a = 1 ) โปรดทราบว่าคุกกี้ที่ตั้งค่าด้วยเส้นทาง/ ตัวอย่าง ( a = 2 ) มีเส้นทางที่ยาวกว่าเส้นทางที่มีเส้นทาง/ ( a = 1 ) ดังนั้น จะถูกส่งกลับถึงคุณก่อนในบรรทัดซึ่งตรงกับคำแนะนำของข้อมูลจำเพาะ ดังนั้นคุณมีความถูกต้องมากหรือน้อยในสมมติฐานของคุณว่าคุณสามารถเลือกค่าแรกได้

น่าเสียดายที่ภาษาที่ใช้ใน RFC มีความเฉพาะเจาะจงอย่างยิ่ง - การใช้คำควรและไม่ควรทำให้เกิดความคลุมเครือใน RFCs สิ่งเหล่านี้บ่งบอกถึงอนุสัญญาที่ควรปฏิบัติตาม แต่ไม่จำเป็นต้องเป็นไปตามข้อกำหนด ในขณะที่ฉันเข้าใจ RFC ในเรื่องนี้ค่อนข้างดี แต่ฉันยังไม่ได้ทำการวิจัยเพื่อดูว่าลูกค้าในโลกแห่งความเป็นจริงทำอะไร เป็นไปได้อย่างน้อยหนึ่งเบราว์เซอร์หรือโปรแกรมอื่น ๆ ที่ทำหน้าที่เป็นไคลเอนต์ HTTP อาจไม่ส่งคุกกี้เส้นทางที่ยาวที่สุด (เช่น/ ตัวอย่าง ) ก่อนในส่วนหัวของคุกกี้:

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

  1. โดยใช้ชื่อคุกกี้อื่นเพื่อแทนที่ในบางเส้นทางเช่น:

    • Set-cookie: a-global = 1; Path = /; Version = 1
    • Set-cookie: a-example = 2; Path = / example; Version = 1
  2. การจัดเก็บเส้นทางที่คุณต้องการในค่าคุกกี้เอง:

    • Set-cookie: a = 1 & path = /; Path = /; Version = 1
    • เซ็ตคุกกี้: a = 2 & path = / example; Path = / example; Version = 1

วิธีแก้ปัญหาทั้งสองนี้ต้องการตรรกะเพิ่มเติมบนเซิร์ฟเวอร์เพื่อเลือกค่าคุกกี้ที่ต้องการโดยเปรียบเทียบ URL ที่ร้องขอกับรายการคุกกี้ที่มี ไม่สวยเกินไป เป็นเรื่องน่าเสียดายที่ RFC ไม่มีการมองการณ์ไกลที่กำหนดให้เส้นทางที่ยาวกว่านั้นจะแทนที่คุกกี้ด้วยเส้นทางที่สั้นกว่าอย่างสมบูรณ์ (เช่นในตัวอย่างของคุณคุณจะได้รับCookie: a = 2 เท่านั้น )


2
ขอขอบคุณที่ขุดสิ่งนี้จาก RFC ที่น่ารังเกียจเหล่านี้! // ทำไมถึงรำคาญถ้าไม่มีใครทำตามคำแนะนำเหล่านี้ ..
Rast

3
ดูเหมือนว่า Wildfly 8.0 จะให้ความสำคัญกับลำดับของคุกกี้และใช้คุกกี้แรก สิ่งนี้ทำให้เราสามารถเรียกใช้แอปอื่นในบริบท "ซ้อน" ได้ อย่างไรก็ตามจะล้มเหลวหากเบราว์เซอร์บางตัวไม่ปฏิบัติตามคำแนะนำของ RFC วิธีที่ถูกต้องในการตั้งชื่อคุกกี้เซสชันอื่นเช่น JSESSIONID2
honzajde

2
ฉันได้ทดสอบเบราว์เซอร์หลัก ๆ หลังจากอ่านคำตอบของคุณ: Chrome 63 / Opera 55 / IE11 / Edge 16 / Safari 11 / Firefox 58 และดูเหมือนว่าพวกเขาทั้งหมดจะจัดการได้อย่างถูกต้องว่า Cookie ที่มีเส้นทางที่ยาวกว่านั้นอยู่ก่อนทางที่สั้นกว่า และใน PHP (ทดสอบในเวอร์ชัน 7) จะอ่านเฉพาะคุกกี้แรกซึ่งตั้งค่าเป็นตัวแปร $ _COOKIE
Alexander Schranz

1
ไม่path=/;Path=/สอดรับข้อกำหนด FRC-6265? ฉันไม่พบการกล่าวถึงดังกล่าว Tomcatคุกคามใด ๆ ";" ในเส้นทางเป็นสัญลักษณ์ที่ไม่ถูกต้อง
Hubbitus

1
@Hubbitus ให้ความสนใจมันa=2&path=/example;Path=/exampleจึงไม่มี;ในเส้นทาง
Franklin Yu

2

ไม่มีอะไรผิดปกติกับการมีหลายค่าสำหรับชื่อเดียวกัน ... ถ้าคุณต้องการ คุณอาจฝังบริบทเพิ่มเติมในค่า

หากคุณไม่ทำเช่นนั้นแน่นอนว่าชื่อที่แตกต่างกันเป็นวิธีแก้ปัญหาหากคุณต้องการทั้งสองบริบท

อีกทางเลือกหนึ่งคือการส่งชื่อคุกกี้เดียวกันที่มีเส้นทางเดียวกัน (และโดเมน) แม้จะมาจากเส้นทางที่เจาะจงกว่าก็ตาม ชุดคำสั่งคุกกี้เหล่านั้นจะเขียนทับค่าของคุกกี้นั้น

ตอนนี้คุณรู้แล้วว่าส่วนที่สำคัญที่สุด (วิธีการทำงาน) และคุณสามารถบรรลุสิ่งที่คุณต้องการได้ด้วยวิธีต่างๆสองสามวิธีแล้วคำตอบของฉันสำหรับคำถามของคุณคือนี่เป็นปัญหาของนักพัฒนา


0

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

ฉันขอแนะนำอย่างยิ่งให้หลีกเลี่ยงการปฏิบัตินี้

อย่างไรก็ตามหากคุณต้องการทราบว่าเบราว์เซอร์ (และแอป) จัดการกับสถานการณ์นี้อย่างไรทำไมไม่ลองสร้างอุปกรณ์ทดสอบและลองใช้ดู


2
เซิร์ฟเวอร์ไม่สามารถควบคุมสิ่งที่เบราว์เซอร์ส่งถึงเซิร์ฟเวอร์ได้ มันยังคงต้องจัดการ
Martin OConnor

0

หากคุณใช้ Java / Scala framework Play: ระวัง! หากคำขอมีคุกกี้หลายตัวที่มีชื่อเดียวกัน Play จะแสดงคุกกี้เพียง 1 รายการในรหัสของคุณ


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