รูปแบบการเข้าสู่ระบบ REST API


181

ฉันกำลังสร้าง REST api อย่างใกล้ชิดทำตามคำแนะนำของ apigee โดยใช้คำนามไม่ใช่คำกริยาเวอร์ชัน api ที่ถูกอบเข้าไปใน url สองเส้นทาง api ต่อการรวบรวม GET POST PUT DELETE การใช้งาน ฯลฯ

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

ตัวเลือกที่เป็นไปได้

  • โพสต์เพื่อบางสิ่งบางอย่างเช่น https://api...com/v1/login.json
  • ใส่เพื่ออะไรเช่น https://api...com/v1/users.json
  • บางสิ่งที่ฉันไม่ได้คิด ...

สไตล์ REST ที่เหมาะสมสำหรับการเข้าสู่ระบบของผู้ใช้คืออะไร?


9
นั่นคือรูปแบบการตอบกลับ .json บอกให้เซิร์ฟเวอร์ตอบสนองด้วย json, .xml บอกให้เซิร์ฟเวอร์ตอบสนองด้วยรูปแบบ xml ค่อนข้างจะทำให้มันเป็นพารามิเตอร์ทางเลือกที่อยู่เบื้องหลัง? blog.apigee.com/detail/…
Scott Roepnack

28
ไม่เคยเห็นการเจรจาต่อรองเนื้อหาที่ทำบน URL เฉพาะในส่วนหัว บน URL หมายความว่าคุณเสียประโยชน์จากการแคชและอื่น ๆ
Oded

10
@ScottRoepnack ดังนั้นคุณควรพิจารณาAcceptส่วนหัว HTTP
Alessandro Vendruscolo

2
@Oded หากคุณใช้Acceptส่วนหัวคุณจะต้องมีVary: Acceptดังนั้นการแคชจะไม่ได้รับผลกระทบ Conneg ในส่วนขยายได้รับการกล่าวถึงก่อน ; ฉันเห็นด้วยกับคำตอบของ Shonzilla ที่นั่น
cmbuckley

2
@Oded - ฉันไม่เข้าใจ เหตุใดคุณจึงสูญเสียผลประโยชน์จากการแคชหากคุณระบุประเภทเนื้อหาใน URL (ไม่ว่าจะเป็นคำต่อท้าย. json ไปยังพา ธ การสืบค้นหรือเป็นพารามิเตอร์การค้นหาแบบ type = json) ในกรณีนี้ใครคือ "คุณ" ใครคือคนที่สูญเสียผลประโยชน์แคช? สำหรับฉันดูเหมือนว่าผลลัพธ์ของแบบสอบถามใด ๆ สามารถถูกแคชได้โดยไม่คำนึงถึงสิ่งที่อยู่ในเส้นทางแบบสอบถามหรือ params
Cheeso

คำตอบ:


138

การออกแบบหลักการของสถาปัตยกรรมเว็บสมัยใหม่โดย Roy T. Fielding และ Richard N. Taylorเช่นลำดับงานจากคำศัพท์ REST ทั้งหมดที่มาจากนั้นมีคำจำกัดความของการโต้ตอบระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์:

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

ข้อ จำกัด นี้ใช้งานได้สี่ฟังก์ชันโดยที่ 1 และ 3 มีความสำคัญในกรณีนี้โดยเฉพาะ:

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

และตอนนี้ให้กลับไปที่กรณีความปลอดภัยของคุณ ทุกคำขอเดียวควรมีข้อมูลที่จำเป็นทั้งหมดและการให้สิทธิ์ / รับรองความถูกต้องจะไม่เป็นข้อยกเว้น ทำอย่างไรจึงจะได้สิ่งนี้? ส่งข้อมูลที่ต้องการอย่างแท้จริงผ่านสายทุกคำขอ

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

มีตัวอย่างมากมายของการใช้งานHMACแต่ฉันอยากให้คุณใส่ใจกับสามสิ่งต่อไปนี้:

มันทำงานอย่างไรในทางปฏิบัติ

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

หวังว่าสิ่งนี้จะช่วยให้คุณค้นหาทางออกที่เหมาะสม!


23
MAC มีไว้เพื่อพิสูจน์ความเป็นข้อความและป้องกันการดัดแปลง - ไม่มีส่วนเกี่ยวข้องกับการพิสูจน์ตัวตนผู้ใช้
yrk

1
เพิ่มหนึ่งในตัวอย่างวิธีจัดการการรับรองความถูกต้องของผู้ใช้ / ลูกค้าโดยไม่ทราบว่า " URL การเข้าสู่ระบบ " ล่วงหน้า
Akim

นี่เป็นอีกสองบทความที่ดีกับตัวอย่างไร้สัญชาติรับรองความถูกต้องสำหรับการให้บริการ REST: blog.jdriven.com/2014/10/... technicalrex.com/2015/02/20/...
วลาดิเมีย Rozhkov

41

TL; DRล็อกอินสำหรับแต่ละคำขอไม่ได้เป็นส่วนประกอบที่จำเป็นสำหรับการใช้งานความปลอดภัยของ API การตรวจสอบความถูกต้องคือ

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

REST ไม่ได้กำหนดกฎความปลอดภัยใด ๆ แต่การใช้งานทั่วไปในทางปฏิบัติคือ OAuth พร้อมการรับรองความถูกต้องแบบ 3 ทาง (ดังที่คุณได้กล่าวถึงในคำถามของคุณ) ไม่มีการเข้าสู่ระบบอย่างน้อยกับคำขอ API แต่ละรายการ ด้วยการรับรองความถูกต้อง 3 วิธีคุณเพียงแค่ใช้โทเค็น

  1. ผู้ใช้อนุมัติลูกค้า API และได้รับอนุญาตให้ทำการร้องขอในรูปแบบของโทเค็นที่มีอายุการใช้งานยาวนาน
  2. ลูกค้า API ได้รับโทเค็นระยะสั้นโดยใช้หนึ่งในระยะยาว
  3. ลูกค้า Api ส่งโทเค็นอายุสั้นที่มีแต่ละคำขอ

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

ฉันไม่คิดว่าคุณควรจะวางกรอบปัญหาของคุณ (และคำถาม) ในแง่ของการเข้าสู่ระบบ แต่คิดว่าเกี่ยวกับการรักษาความปลอดภัย API โดยทั่วไป

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการรับรองความถูกต้องของ REST API โดยทั่วไปคุณสามารถดูทรัพยากรต่อไปนี้:


ใช่แล้ว OAuth! คำตอบที่ตรงไปตรงมามากควรเป็นคำตอบที่ยอมรับได้ imho
Levite

26

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

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

แต่สำหรับ REST API หน้าจอเข้าสู่ระบบและคุกกี้เซสชันไม่จำเป็นอย่างเคร่งครัดเนื่องจากแต่ละคำขอสามารถมีข้อมูลรับรองโดยไม่ส่งผลกระทบต่อผู้ใช้ที่เป็นมนุษย์ และหากลูกค้าไม่ให้ความร่วมมือในเวลาใดก็ได้401สามารถให้คำตอบ "ไม่ได้รับอนุญาต" ได้ RFC 2617อธิบายการสนับสนุนการรับรองความถูกต้องใน HTTP

TLS (HTTPS) จะเป็นตัวเลือกและอนุญาตให้มีการตรวจสอบความถูกต้องของไคลเอนต์ไปยังเซิร์ฟเวอร์ (และในทางกลับกัน) ในทุกคำขอโดยการตรวจสอบกุญแจสาธารณะของอีกฝ่าย นอกจากนี้ยังช่วยรักษาช่องทางให้ได้รับโบนัสด้วย แน่นอนการแลกเปลี่ยนกุญแจคู่ก่อนการสื่อสารเป็นสิ่งจำเป็นในการทำเช่นนี้ (หมายเหตุนี่เป็นเรื่องเกี่ยวกับการระบุ / รับรองความถูกต้องของผู้ใช้ด้วย TLS การรักษาความปลอดภัยช่องโดยใช้ TLS / Diffie-Hellman เป็นความคิดที่ดีเสมอแม้ว่าคุณจะไม่ได้ระบุผู้ใช้ด้วยรหัสสาธารณะ)

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


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

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

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

ความแตกต่างระหว่างคุกกี้และส่วนหัวการรับรองความถูกต้องเป็นข้อมูลประจำตัวคือคุกกี้จะเชื่อมโยงกับโดเมนเฉพาะเสมอ ซึ่งหมายความว่าเมื่อ API ได้รับคุกกี้จะรู้ว่ามาจากไหน (เขียนโดยโดเมนเดียวกันก่อนหน้านี้) ด้วยหัวข้อที่คุณไม่เคยรู้และคุณต้องใช้การตรวจสอบเฉพาะสำหรับเรื่องนี้ โดยทั่วไปฉันเห็นด้วยพวกเขาเป็นข้อมูลประจำตัวทั้งสอง แต่ฉันคิดว่าการส่งผ่านข้อมูลประจำตัวไม่ใช่การเข้าสู่ระบบ เข้าสู่ระบบคือการกระทำที่ใช้งานของการเปิดประตู ในกรณีของการรับรองความถูกต้องแบบ 3 ทางเฉพาะการอนุมัติครั้งแรกของลูกค้าเท่านั้นที่จะเป็นการเข้าสู่ระบบ
Slavo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.