JWT เทียบกับคุกกี้สำหรับการพิสูจน์ตัวตนที่ใช้โทเค็น


114

ฉันอ่านโพสต์เกี่ยวกับ"JWT vs Cookie"แต่มันทำให้ฉันสับสนมากขึ้นเท่านั้น ...

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

  2. ทำไมเราต้องโทเค็นเว็บ JSON ? ฉันใช้คุกกี้มาตรฐานเพื่อใช้การรับรองความถูกต้องโดยใช้โทเค็น ( ไม่ใช้รหัสเซสชันไม่ใช้หน่วยความจำเซิร์ฟเวอร์หรือที่เก็บไฟล์ ): Set-Cookie: user=innocent; preferred-color=azureและข้อแตกต่างเพียงอย่างเดียวที่ฉันสังเกตเห็นคือ JWT มีทั้งน้ำหนักบรรทุกและลายเซ็น ... ในขณะที่คุณสามารถเลือกได้ ระหว่างคุกกี้ที่ลงชื่อหรือข้อความธรรมดาสำหรับส่วนหัว http ในความคิดของฉันคุกกี้ที่ลงชื่อ ( cookie:'time=s%3A1464743488946.WvSJxbCspOG3aiGi4zCMMR9yBdvS%2B6Ob2f3OG6%2FYCJM') มีประสิทธิภาพในการใช้พื้นที่มากกว่าข้อเสียเปรียบเพียงประการเดียวคือไคลเอนต์ไม่สามารถอ่านโทเค็นได้มีเพียงเซิร์ฟเวอร์เท่านั้นที่ทำได้ ... แต่ฉันคิดว่าดีเพราะเช่นเดียวกับการอ้างสิทธิ์ใน JWT เป็นทางเลือกไม่จำเป็นสำหรับโทเค็น มีความหมาย

คำตอบ:


166

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

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

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

สมมติว่าเว็บไซต์ที่https://www.example.comอนุญาตให้ผู้ใช้ที่ได้รับการพิสูจน์ตัวตนสามารถเปลี่ยนรหัสผ่านได้โดยPOSTตั้งรหัสผ่านใหม่เป็นhttps://www.example.com/changepasswordโดยไม่ต้องโพสต์ชื่อผู้ใช้หรือรหัสผ่านเดิม

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

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

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


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

17
@kbuilds Only คือเพจที่เป็นอันตรายกำลังใช้ AJAX เพื่อโพสต์แบบฟอร์ม หากผู้โจมตีให้คุณคลิกปุ่มส่งในรูปแบบปกติ CORS จะไม่เข้ามาเล่น
MvdD

3
แต่นี่ไม่ได้หมายความว่าไซต์จะมีช่องโหว่ก็ต่อเมื่อไม่มีการใช้โทเค็น CSRF
สร้าง

5
ใช่แล้วคุณสามารถลดการโจมตี CSRF ได้โดยใช้โทเค็น CSRF แต่นี่เป็นสิ่งที่คุณต้องทำอย่างชัดเจน
MvdD

2
การใช้คุกกี้ช่วยปกป้องคุณจากการโจมตี XSS อย่างไรก็ตามเพื่อให้สามารถตั้งค่าส่วนหัวการอนุญาตได้คุณจะต้องเข้าถึงโทเค็นการเข้าถึงจากจาวาสคริปต์ การป้องกันตัวเองจาก CSRF เป็นเรื่องง่าย แต่ XSS ป้องกันได้ยากกว่ามาก - โทเค็นของผู้ถือมีความหมายมากกว่า แต่มาพร้อมกับราคา
kataik

103

ภาพรวม

สิ่งที่คุณต้องการคือความแตกต่างระหว่างคุกกี้และโทเค็นผู้ถือสำหรับการส่ง JSON Web Tokens (JWTs) จากไคลเอนต์ไปยังเซิร์ฟเวอร์

ทั้งคุกกี้และโทเค็นผู้ถือส่งข้อมูล

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

ข้อมูลนั้นมักถูกเข้ารหัสเป็น JWT

คุกกี้

คุกกี้คือคู่ชื่อ - ค่าที่เก็บไว้ในเว็บเบราว์เซอร์และมีวันหมดอายุและโดเมนที่เกี่ยวข้อง

เราจัดเก็บคุกกี้ในเว็บเบราว์เซอร์ด้วย JavaScript หรือด้วยส่วนหัวการตอบสนอง HTTP

document.cookie = 'my_cookie_name=my_cookie_value'   // JavaScript
Set-Cookie: my_cookie_name=my_cookie_value           // HTTP Response Header

เว็บเบราว์เซอร์จะส่งคุกกี้โดยอัตโนมัติพร้อมทุกคำขอไปยังโดเมนของคุกกี้

GET http://www.bigfont.ca
Cookie: my_cookie_name=my_cookie_value               // HTTP Request Header

ถือโทเค็น

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

GET http://www.bigfont.ca
Authorization: Bearer my_bearer_token_value          // HTTP Request Header

JWTและ Token Based Authentication

เมื่อเราทำการตรวจสอบความถูกต้องโดยใช้โทเค็นเช่น OpenID, OAuth หรือ OpenID Connect เราจะได้รับ access_token (และบางครั้งก็ id_token) จากหน่วยงานที่เชื่อถือได้ โดยปกติเราต้องการจัดเก็บและส่งไปพร้อมกับคำขอ HTTP สำหรับทรัพยากรที่มีการป้องกัน เราจะทำอย่างนั้นได้อย่างไร?

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

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

ควรอ่าน RFC ที่เชื่อมโยงเพื่อเรียนรู้เพิ่มเติม


22

นอกเหนือจากสิ่งที่ MvdD กล่าวเกี่ยวกับคุกกี้ที่ถูกส่งโดยอัตโนมัติ:

  1. คุกกี้อาจเป็นสื่อได้ แต่หน้าที่ที่สำคัญที่สุดคือวิธีที่มันโต้ตอบกับเบราว์เซอร์ เซิร์ฟเวอร์กำหนดคุกกี้และส่งคำขอในรูปแบบที่เฉพาะเจาะจงมาก ในทางกลับกัน JWT เป็นสื่อเพียงอย่างเดียวเป็นการยืนยันข้อเท็จจริงบางอย่างในโครงสร้างเฉพาะ หากคุณชอบมากคุณสามารถใส่ JWT เป็นคุกกี้การตรวจสอบสิทธิ์ของคุณได้ เมื่อคุณอ่านบทความเปรียบเทียบพวกเขามักจะพูดถึงการใช้ JWT ที่ส่งเป็นโทเค็นผู้ถือด้วยรหัสส่วนหน้าเทียบกับคุกกี้การตรวจสอบความถูกต้องซึ่งสอดคล้องกับเซสชันที่แคชหรือข้อมูลผู้ใช้ที่ส่วนหลัง
  2. JWT นำเสนอคุณสมบัติมากมายและวางไว้ในมาตรฐานเพื่อให้สามารถใช้ระหว่างฝ่ายต่างๆได้ JWT สามารถทำหน้าที่เป็นผู้ลงนามยืนยันข้อเท็จจริงบางอย่างในหลาย ๆ ที่ คุกกี้ไม่ว่าคุณจะใส่ข้อมูลใดลงไปหรือหากคุณลงชื่อเข้าใช้จะมีความสมเหตุสมผลที่จะใช้ระหว่างเบราว์เซอร์และส่วนหลังที่เฉพาะเจาะจง JWT สามารถใช้ได้จากเบราว์เซอร์ไปจนถึงแบ็คเอนด์ระหว่างแบ็คเอนด์ที่ควบคุมโดยฝ่ายต่างๆ (OpenId Connect เป็นตัวอย่าง) หรือภายในบริการแบ็คเอนด์ของฝ่ายหนึ่ง สำหรับตัวอย่างเฉพาะของคุกกี้ที่คุณลงชื่อคุณอาจใช้ฟังก์ชันเดียวกัน ("ไม่ใช้รหัสเซสชันไม่ใช้หน่วยความจำเซิร์ฟเวอร์หรือที่เก็บไฟล์") เป็น JWT ในกรณีการใช้งานนั้น แต่คุณสูญเสียไลบรารีและการตรวจสอบโดยเพื่อนของ มาตรฐานนอกเหนือจากประเด็น CSRF ที่พูดถึงในคำตอบอื่น ๆ

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


4
ทำได้ดีมากโดยชี้แจงว่าการเปรียบเทียบระหว่างโทเค็นของผู้ถือและคุกกี้จริงๆ
Shaun Luttin

15

แม้ว่าคุกกี้สามารถเพิ่มความเสี่ยงของการโจมตี CSRF โดยอาศัยการส่งโดยอัตโนมัติพร้อมกับคำขอ แต่ก็สามารถลดความเสี่ยงของการโจมตี XSS ได้เมื่อHttpOnlyตั้งค่าสถานะเนื่องจากสคริปต์ใด ๆ ที่ถูกแทรกเข้าไปในหน้าเว็บจะไม่สามารถอ่านได้ คุกกี้

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

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


3

Ref - ต้องการโทเค็นเว็บ JSON

คุ้กกี้

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

ป้อนคำอธิบายภาพที่นี่

ข้อเสียของคุกกี้

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

ป้อนคำอธิบายภาพที่นี่

จว

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

ป้อนคำอธิบายภาพที่นี่

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