การตรวจสอบความถูกต้อง: การใช้งาน JWT เทียบกับเซสชัน


123

ข้อดีของการใช้ JWT ในเซสชันในสถานการณ์เช่นการพิสูจน์ตัวตนคืออะไร?

ใช้เป็นวิธีการแบบสแตนด์อโลนหรือใช้ในเซสชัน?

คำตอบ:


213

JWT ไม่มีประโยชน์จากการใช้ "เซสชัน" ต่อการพูด JWT มีวิธีการรักษาสถานะเซสชันบนไคลเอนต์แทนการทำบนเซิร์ฟเวอร์

สิ่งที่ผู้คนมักจะหมายถึงเมื่อถามนี้คือ "อะไรคือประโยชน์ของการใช้ JWTs มากกว่าใช้การประชุมฝั่งเซิร์ฟเวอร์ "

ด้วยเซสชันฝั่งเซิร์ฟเวอร์คุณจะต้องจัดเก็บตัวระบุเซสชันในฐานข้อมูลหรือไม่ก็เก็บไว้ในหน่วยความจำและตรวจสอบให้แน่ใจว่าไคลเอนต์เข้าสู่เซิร์ฟเวอร์เดียวกันเสมอ ทั้งสองอย่างนี้มีข้อบกพร่อง ในกรณีของฐานข้อมูล (หรือที่เก็บข้อมูลส่วนกลางอื่น ๆ ) สิ่งนี้จะกลายเป็นคอขวดและเป็นสิ่งที่ต้องดูแล - โดยพื้นฐานแล้วจะเป็นแบบสอบถามพิเศษที่ต้องทำกับทุกคำขอ

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

การย้ายเซสชันไปยังไคลเอนต์หมายความว่าคุณลบการพึ่งพาเซสชันฝั่งเซิร์ฟเวอร์ แต่เป็นการกำหนดชุดความท้าทายของตัวเอง

  • การจัดเก็บโทเค็นอย่างปลอดภัย
  • ขนส่งอย่างปลอดภัย
  • บางครั้งเซสชัน JWT อาจทำให้เป็นโมฆะได้ยาก
  • ไว้วางใจการเรียกร้องของลูกค้า

ปัญหาเหล่านี้แชร์โดย JWT และกลไกเซสชันฝั่งไคลเอ็นต์อื่น ๆ

JWT โดยเฉพาะที่อยู่สุดท้ายของสิ่งเหล่านี้ อาจช่วยให้เข้าใจว่า JWT คืออะไร:

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

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

ในปัญหาเกี่ยวกับการขนส่งโทเค็นอย่างปลอดภัยคำตอบมักจะส่งผ่านช่องทางเข้ารหัสซึ่งโดยปกติจะเป็น httpS

เกี่ยวกับการจัดเก็บโทเค็นอย่างปลอดภัยในไคลเอนต์คุณต้องมั่นใจว่าคนร้ายไม่สามารถเข้าถึงได้ (ส่วนใหญ่) หมายถึงการป้องกัน JS จากเว็บไซต์ที่ไม่ดีไม่ให้อ่านโทเค็นเพื่อส่งกลับไปให้ สิ่งนี้บรรเทาได้โดยใช้กลยุทธ์เดียวกับที่ใช้ในการลดการโจมตี XSS ประเภทอื่น ๆ

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

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

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

สรุปสั้น ๆ : JWTs ตอบคำถามและข้อบกพร่องของเทคนิคเซสชั่นอื่น ๆ

  1. การรับรองความถูกต้อง "ถูกกว่า" เนื่องจากคุณสามารถกำจัด DB ไปกลับ (หรืออย่างน้อยก็มีตารางที่เล็กกว่ามากสำหรับการสืบค้น!) ซึ่งจะช่วยให้สามารถปรับขนาดได้ในแนวนอน
  2. การอ้างสิทธิ์ฝั่งไคลเอ็นต์ที่ป้องกันการงัดแงะ

แม้ว่า JWT จะไม่ตอบโจทย์ปัญหาอื่น ๆ เช่นการจัดเก็บที่ปลอดภัยหรือการขนส่ง แต่ก็ไม่ได้แนะนำปัญหาด้านความปลอดภัยใหม่ ๆ

มีการปฏิเสธมากมายรอบ ๆ JWT แต่ถ้าคุณใช้การรักษาความปลอดภัยแบบเดียวกับที่คุณใช้สำหรับการตรวจสอบสิทธิ์ประเภทอื่นคุณก็จะสบายดี

หมายเหตุสุดท้าย: นอกจากนี้ยังไม่ใช่คุกกี้เทียบกับโทเค็น คุกกี้เป็นกลไกในการจัดเก็บและขนส่งข้อมูลบิตและสามารถใช้เพื่อจัดเก็บและขนส่งโทเค็น JWT ได้ด้วย


4
เป็นที่น่าสังเกตว่าเซสชันฝั่งเซิร์ฟเวอร์ไม่จำเป็นต้องจัดเก็บข้อมูลใด ๆ บนเซิร์ฟเวอร์เช่นกัน เซิร์ฟเวอร์สามารถใช้ไคลเอ็นต์เป็นที่เก็บได้เช่นเดียวกับที่ JWT ทำ ความแตกต่างที่แท้จริงคือ 1) หลีกเลี่ยงกฎการรักษาความปลอดภัยของเบราว์เซอร์โดยส่งค่าเป็นส่วนหัวของคำขอนอกเหนือจากส่วนหัวของคุกกี้และ 2) มีรูปแบบมาตรฐานด้วย JWT
Xeoncross

1
คุณจะบอกว่าการจัดเก็บ jwt ในที่จัดเก็บในเครื่องปลอดภัยหรือไม่? ถ้าไม่มีสถานที่ที่ปลอดภัยในการบันทึกเพื่อให้ผู้ใช้อยู่ในระบบอยู่ที่ไหน
Jessica

1
ใช่ localstorage เป็นสถานที่ที่ถูกต้องที่สุดในการจัดเก็บฝั่งไคลเอ็นต์ คุณจำเป็นต้องจัดการกับ XSS - ฉันไม่ใช่ผู้เชี่ยวชาญด้านการเขียนโปรแกรมบนเว็บ แต่ดูคำตอบนี้stackoverflow.com/a/40376819/1810447และค้นหา "How To Protect Against XSS"
The Tahaan

1
ในความคิดเห็นของคุณคุณไม่ได้พูดถึงโซลูชันที่ใช้แคช + โทเค็นเซสชัน สำหรับฉันมันฟังดู "ดี" กว่าตาราง "โทเค็นที่ถูกฆ่า" ของ JWT + เพราะด้วยตาราง "โทเค็นที่ถูกฆ่า" นี้คุณจำเป็นต้องมีการเข้าถึงฐานข้อมูลซึ่งคุณจะมีเซสชัน + แคชด้วย (ซึ่งมีขนาดเล็กเช่นกัน) และการคงอยู่ JWT นั้นเจ็บปวดในการใช้งานมากกว่าเซสชันที่มีอยู่เนื่องจากคุณต้องเล่นกับ refresh_token (เพื่อรักษาสองโทเค็น) ... ความคิดเห็นใด ๆ จะได้รับการชื่นชมอย่างมาก ... โดยเฉพาะอย่างยิ่งหากคุณมีตัวเลขที่จะแสดงว่า JWT + เป็นอย่างไร kill_table มีประสิทธิภาพมากกว่าเซสชัน + แคช ;-)
tobiasBora

2
@TheTahaan localStorage ไม่แนะนำให้จัดเก็บ JWT ลิงก์ที่คุณแชร์ก็ระบุเช่นกัน บล็อกนี้มีคำอธิบายที่ดีว่าเหตุใดจึงไม่ควรจัดเก็บ JWT ใน localStorage
Harke

40

คำตอบสั้น ๆ คือ: ไม่มี

เวอร์ชันที่ยาวกว่าคือ:

ฉันใช้ JWT สำหรับการจัดการเซสชันหลังจากอ่านคำแนะนำนี้ในเอกสาร GraphQL :

หากคุณไม่คุ้นเคยกับกลไกการตรวจสอบสิทธิ์เหล่านี้เราขอแนะนำให้ใช้ express-jwt เพราะง่ายโดยไม่ต้องเสียสละความยืดหยุ่นในอนาคต

การติดตั้งใช้งานนั้นง่ายมากเพราะมันเพิ่มความซับซ้อนเล็กน้อยเท่านั้น หลังจากนั้นไม่นานฉัน (เช่นคุณ) เริ่มสงสัยว่าประโยชน์คืออะไร ปรากฎว่ามี JWT น้อยมาก (หรืออาจไม่มีเลย) สำหรับ JWT เท่าที่การจัดการเซสชันดำเนินไปตามที่บล็อกโพสต์นี้อธิบายรายละเอียด:

หยุดใช้ JWT สำหรับเซสชัน


0

สองเซ็นต์ของฉันซึ่งระหว่างทางเพิ่มความแตกต่างให้กับบล็อกโพสต์ที่มีชื่อเสียงของ joepie91

พิจารณาว่าในวันนี้ (และในวันพรุ่งนี้) การใช้กำลัง (ส่วนใหญ่) เมฆพื้นเมือง
มีผลประโยชน์ทางเศรษฐกิจที่จะเป็นคนไร้รัฐ JWT รับรองความถูกต้องซึ่งเครื่องชั่งน้ำหนักเครื่องชั่งของโปรแกรมประยุกต์: การใช้งานระบบคลาวด์เสียค่าใช้จ่ายพร้อมกับทุกลมหายใจหนึ่งดึง

ค่าใช้จ่ายนี้จะลดลงเมื่อผู้ใช้ไม่ต้องตรวจสอบสิทธิ์ "กับ" ที่เก็บเซสชันอีกต่อไป

การ
ดำเนินการจัดเก็บเซสชัน 24/7 มีค่าใช้จ่าย
คุณไม่สามารถหลีกหนีจากโซลูชันที่ใช้หน่วยความจำในโลกของ K8S ได้เนื่องจากพ็อดเป็นเพียงชั่วคราว
เซสชันเหนียวจะไม่ได้ผลดีด้วยเหตุผลเดียวกัน

การจัด
เก็บการจัดเก็บข้อมูลมีค่าใช้จ่าย การจัดเก็บข้อมูลในSSD มีค่าใช้จ่ายมากขึ้น
การดำเนินการที่เกี่ยวข้องกับเซสชันจำเป็นต้องได้รับการแก้ไขอย่างรวดเร็วดังนั้นออปติคัลไดรฟ์จึงไม่ใช่ตัวเลือก

I / O
ผู้ให้บริการระบบคลาวด์บางรายเรียกเก็บเงินสำหรับ I / O ที่เกี่ยวข้องกับดิสก์

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

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


"คุณไม่สามารถหลีกหนีจากโซลูชันที่ใช้หน่วยความจำในโลกของ K8S ได้เนื่องจากพ็อดเป็นเพียงชั่วคราว" ไม่แน่ใจว่าคุณหมายถึงอะไร Redis ทำงานในสภาพแวดล้อม K8S ได้อย่างแน่นอนและ Redis pod ล้มเหลวบ่อยพอที่จะส่งผลกระทบต่อผู้ใช้ของคุณดูเหมือนไม่น่าเป็นไปได้มาก
quietContest

@quietContest โดยส่วนตัวแล้วฉันไม่ต้องการจัดการกับความเป็นไปได้ในการสร้างซอฟต์แวร์ BTW, ความเสถียรของโซลูชันนอกเหนือจากการโจมตีอาจทำให้ซอฟต์แวร์ล้มเหลวและพ็อดเริ่มต้นใหม่ซึ่งจะส่งผลให้สูญเสียเซสชัน ฉันเลือกใช้โซลูชันที่ใช้ JWT ด้วยเหตุผลนั้น
Eyal Perry

1
"โดยส่วนตัวแล้วฉันไม่ต้องการจัดการกับความเป็นไปได้ในการสร้างซอฟต์แวร์" ฉันคิดว่าเราทุกคนคงชอบสิ่งนั้นซึ่งเป็นเหตุผลว่าทำไมเราไม่ควรออกแบบระบบที่อาศัยการจัดเก็บข้อมูลในหน่วยความจำไม่เคยล้มเหลวเพราะความเป็นไปได้ที่จะเกิดขึ้นนั้นสูงพอสมควร ในอีกประเด็นหนึ่งของคุณหากคุณมีผู้โจมตีที่สามารถปิดอินสแตนซ์ redis ของคุณได้อย่างสม่ำเสมอวิธีแก้ปัญหานั้นอาจไม่จำเป็นต้องเกี่ยวข้องกับการใช้ JWT
quietContest

@quietContest อย่างต่อเนื่องหรือเหตุการณ์ครั้งหนึ่งในชีวิตก็เหมือนกับฉันในแง่มุมนี้ กล่าวคือการโจมตี DDoS ที่วางไว้อย่างดีสามารถทำให้เซิร์ฟเวอร์ "ล็อกผู้ใช้ออก" ได้ สิ่งนี้ไม่ดีต่อชื่อเสียงความน่าเชื่อถือของซอฟต์แวร์ ฉันคิดว่า redis มากเกินไปสำหรับการจัดการเซสชั่นอยู่ดี มีค่าใช้จ่ายและจำเป็นต้องปรับขนาดในขณะที่ (อย่างปลอดภัย) การจัดเก็บ JWT ในคุกกี้ไม่ได้
Eyal Perry

1
@quietContest ขอบคุณสำหรับข้อมูลของคุณรักการสนทนา!
Eyal Perry

0

ฉันมีคำถามที่คล้ายกันในการเลือกระหว่าง JWT และโทเค็น + แคชสำหรับการตรวจสอบผู้ใช้

หลังจากอ่านบทความเหล่านี้ฉันเห็นได้ชัดว่าประโยชน์ที่สัญญาของ JWT ไม่ได้แซงหน้าปัญหาที่เกิดขึ้น โทเค็น + แคช (Redis / Memcached) จึงเป็นวิธีที่จะไปสำหรับฉัน

Auth Headers vs JWT vs Sessions - วิธีเลือกเทคนิค Auth ที่เหมาะสมสำหรับ API

เทคนิคการพิสูจน์ตัวตนสำหรับ API

หยุดใช้ jwt สำหรับเซสชัน

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