JavaScript: การตรวจสอบฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์


179

การตรวจสอบความถูกต้องด้านไคลเอนต์หรือฝั่งเซิร์ฟเวอร์ดีกว่ากัน?

ในสถานการณ์ของเราเรากำลังใช้

  • jQuery และ MVC
  • ข้อมูล JSON ที่จะผ่านระหว่างมุมมองและตัวควบคุมของเรา

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

ฉันเดาคำถามที่ดีกว่าจะมีประโยชน์ในการทำการตรวจสอบฝั่งเซิร์ฟเวอร์มากกว่าฝั่งลูกค้าหรือไม่


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


2
javascript สามารถปิดการใช้งานได้
Enrico Murru

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

คำตอบ:


347

อย่างที่คนอื่นพูดคุณควรทำทั้งสองอย่าง นี่คือเหตุผล:

ด้านลูกค้า

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

หากคุณตรวจสอบความถูกต้องบนเซิร์ฟเวอร์พวกเขาจะต้องส่งแบบฟอร์มรับข้อความแสดงข้อผิดพลาดและพยายามตามหาปัญหา

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

ฝั่งเซิร์ฟเวอร์

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

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

( นี่ไม่ใช่เชิงทฤษฎีเช่นฉันทำงานกับเครื่องมือค้นหาการเดินทางที่ส่งการค้นหาของผู้ใช้ไปยังสายการบินพันธมิตรหลาย บริษัท รถบัส ฯลฯ โดยส่งPOSTคำขอราวกับว่าผู้ใช้กรอกฟอร์มการค้นหาของแต่ละ บริษัท แล้วรวบรวมและเรียงลำดับ ผลลัพธ์ทั้งหมดฟอร์ม JS ของ บริษัท เหล่านั้นไม่เคยดำเนินการและเป็นสิ่งสำคัญสำหรับเราที่พวกเขาให้ข้อความแสดงข้อผิดพลาดใน HTML ที่ส่งคืนแน่นอน API จะดี แต่นี่คือสิ่งที่เราต้องทำ )

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

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

ภาคผนวก - ธันวาคม 2559

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


30
นี่ควรเป็นคำตอบที่ได้รับการยอมรับแม้ในอีก 6 ปีต่อมา: P
Jacob McKay

17
ใช่ฉันต้องการรอเกือบ 10 ปีเพื่อให้แน่ใจ
Brad8118

2
@ kidmosey "เป็นการละเมิดหลักการ DRY ที่ชัดเจน" ใช่ซึ่งหมายถึงความเจ็บปวดสำหรับโปรแกรมเมอร์เช่นเรา แต่ลองจินตนาการถึงรูปแบบการสมัคร หากการทำซ้ำความรู้ "ที่อยู่อีเมลจะต้องมี @" ในรหัสลูกค้าหมายความว่าผู้ใช้จะได้รับข้อเสนอแนะที่เร็วขึ้นและมากขึ้นในการสมัครสมาชิกส่งผลให้รายได้พิเศษ $ 100k ต่อปีมากกว่าการจ่ายค่าบำรุงรักษาเพิ่มเติม DRY เป็นหลักการที่ดีมาก แต่ไม่ใช่การพิจารณาเท่านั้น คุณภาพของรหัสนั้นวัดได้จริงว่ามันให้บริการแก่ผู้ใช้และองค์กรในการวิเคราะห์ต้นทุน / ผลประโยชน์
นาธานลอง

1
@ArunRaaj ใช่แล้วคุณจะพบปัญหาส่วนใหญ่ในแบบนั้น แต่ก็ไม่น่าเชื่อถือ 100% หากผู้ใช้สองคนกรอกแบบฟอร์มพร้อมกันพวกเขาทั้งคู่อาจได้รับแจ้งว่าuser1เป็นชื่อผู้ใช้ที่มีอยู่ เมื่อพวกเขาส่งพวกเขาทั้งสองจะได้รับชื่อผู้ใช้เดียวกันเว้นแต่คุณจะตรวจสอบฝั่งเซิร์ฟเวอร์อีกครั้ง และแม้กระทั่งการตรวจสอบในรหัสแอปพลิเคชันเซิร์ฟเวอร์อาจมีปัญหาเดียวกัน: มีคำขอสองคำขอเข้ามาครั้งแรกที่ตรวจสอบฐานข้อมูลและบอกว่าตกลงครั้งที่สองตรวจสอบฐานข้อมูลและแจ้งว่าตกลงครั้งแรกถูกบันทึกครั้งที่สอง เป็นรายการซ้ำ เฉพาะข้อ จำกัด ที่ไม่ซ้ำกันของ db รับประกันความเป็นเอกลักษณ์
Nathan Long

1
@NathanLong การตรวจสอบความถูกต้องของข้อมูลที่มีความอ่อนไหวต่อสภาพการแข่งขันนั้นไม่ได้เป็นเรื่องที่เข้มงวดเพราะประโยคนี้ทำให้พวกเขาฟัง เป็นเรื่องยากที่จะทำอย่างถูกต้อง แต่สร้างกลไกการจองที่ใช้ทรัพยากรที่ซิงโครไนซ์เพื่อร้องขอ ดังนั้นหากผู้ใช้พิมพ์ "usernameA" การตรวจสอบที่ไม่ซ้ำกันบนเซิร์ฟเวอร์ที่ไม่อนุญาตให้โทรหลายสายพร้อมกันเพื่อตรวจสอบว่าไม่ซ้ำกัน; หากไม่ซ้ำกันให้สำรองด้วยโทเค็นชั่วคราวที่กำหนดให้กับลูกค้าที่เปิดตัวด้วยหากมีการทดสอบชื่อผู้ใช้อื่นด้วยรหัสเซสชันเดียวกัน โทเค็นควรหมดอายุหลังจากเวลาที่เหมาะสม ตัวอย่าง: การสำรองที่นั่ง TicketMaster
Elaskanator

79

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


43

ฉันจะทำซ้ำเพราะมันสำคัญมาก:

ตรวจสอบความถูกต้องบนเซิร์ฟเวอร์เสมอ

และเพิ่ม JavaScript สำหรับการตอบสนองของผู้ใช้


31

ประโยชน์ของการทำการตรวจสอบฝั่งเซิร์ฟเวอร์ผ่านการตรวจสอบฝั่งไคลเอ็นต์คือการตรวจสอบฝั่งไคลเอ็นต์สามารถข้าม / จัดการได้:

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

ในระยะสั้น - เสมอให้ตรวจสอบฝั่งเซิร์ฟเวอร์เสมอจากนั้นพิจารณาการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์ว่าเป็นการเพิ่ม "พิเศษ" เพื่อปรับปรุงประสบการณ์ผู้ใช้ปลายทาง


18

คุณจะต้องเสมอตรวจสอบความถูกต้องบนเซิร์ฟเวอร์เสมอ

การมีการตรวจสอบความถูกต้องของไคลเอนต์ก็ดีสำหรับผู้ใช้ แต่ก็ไม่ปลอดภัยอย่างเต็มที่


9

ฉันยังหาห้องตอบได้

นอกจากคำตอบจาก Rob และ Nathan ฉันจะเพิ่มว่าการตรวจสอบด้านลูกค้ามีความสำคัญ เมื่อคุณใช้การตรวจสอบความถูกต้องกับเว็บฟอร์มของคุณคุณต้องปฏิบัติตามแนวทางเหล่านี้:

ด้านลูกค้า

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

ฝั่งเซิร์ฟเวอร์

  1. คุณไม่ควรถือว่าการตรวจสอบที่ทำสำเร็จในฝั่งไคลเอ็นต์นั้นสมบูรณ์แบบ 100% ไม่สำคัญแม้ว่าจะรองรับผู้ใช้น้อยกว่า 50 รายก็ตาม คุณไม่เคยรู้ว่าผู้ใช้คนใด / กลายเป็น "คนชั่ว" และทำกิจกรรมที่เป็นอันตรายซึ่งรู้ว่าคุณไม่มีการตรวจสอบที่เหมาะสม
  2. แม้ว่าจะสมบูรณ์แบบในแง่ของการตรวจสอบที่อยู่อีเมลหมายเลขโทรศัพท์หรือตรวจสอบอินพุตที่ถูกต้อง แต่ก็อาจมีข้อมูลที่เป็นอันตรายมาก ซึ่งต้องถูกกรองที่ฝั่งเซิร์ฟเวอร์ไม่ว่าจะถูกหรือผิด
  3. หากการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์การตรวจสอบความถูกต้องฝั่งเซิร์ฟเวอร์ของคุณมาช่วยคุณจากความเสียหายที่อาจเกิดขึ้นกับการประมวลผลฝั่งเซิร์ฟเวอร์ของคุณ ในช่วงเวลาที่ผ่านมาเราเคยได้ยินเรื่องราวมากมายของ SQL Injections และเทคนิคอื่น ๆ ที่อาจนำมาใช้เพื่อให้ได้รับผลประโยชน์ที่ไม่ดี

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


ฉันเคยเห็นผู้คนละเลยที่จะป้องกันการฉีดโค้ดโดยสิ้นเชิงไม่ต้องสนใจที่ลูกค้าเท่านั้น และไม่มีการอ้างอิงถึงการฉีดโค้ดเสร็จสมบูรณ์หากไม่ได้เชื่อมโยงไปยังสิ่งนี้: xkcd.com/327 :)
Stewart

8

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


3
ผู้ใช้เป็นมิตร? อาจจะ. เกือบจะทันทีและเนยเนียน อาจจะไม่.
quadrupleslap

4

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


"แต่การตรวจสอบหลักควรเกิดขึ้นที่ฝั่งเซิร์ฟเวอร์" ไม่ควรจะต้อง
Stewart

4

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

คุณสามารถค้นหาข้อมูลที่เกี่ยวข้องบางอย่างที่นี่ https://web.archive.org/web/20131210085944/http://www.webexpertlabs.com/server-side-form-validation-using-regular-expression/


2

JavaScript สามารถแก้ไขได้ที่รันไทม์

ฉันแนะนำรูปแบบของการสร้างโครงสร้างการตรวจสอบความถูกต้องบนเซิร์ฟเวอร์และแบ่งปันสิ่งนี้กับลูกค้า

คุณจะต้องใช้ตรรกะการตรวจสอบแยกต่างหากที่ปลายทั้งสองเช่น:

"required"คุณลักษณะในinputsฝั่งไคลเอ็นต์

field.length > 0 ฝั่งเซิร์ฟเวอร์

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


2

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

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


1

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

Client-Side validationเหมาะสมอย่างยิ่งสำหรับการป้องกันข้อผิดพลาดโดยรวมและแบบสุ่ม โดยทั่วไปความยาวสูงสุดสำหรับพื้นผิวและอินพุต อย่าเลียนแบบกฎการตรวจสอบฝั่งเซิร์ฟเวอร์ จัดเตรียมกฎการตรวจสอบความถูกต้องกฎขั้นต้นด้วยนิ้วหัวแม่มือของคุณเอง (เช่น 200 ตัวอักษรบนฝั่งไคลเอ็นต์; ฝั่งnเซิร์ฟเวอร์ที่กำหนดโดยกฎทางธุรกิจที่แข็งแกร่ง)

Server-side validationเหมาะสมกับการป้องกันข้อผิดพลาดอย่างเป็นระบบ มันจะบังคับใช้กฎเกณฑ์ทางธุรกิจ

ในโครงการที่ฉันเข้าร่วมการตรวจสอบความถูกต้องจะทำบนเซิร์ฟเวอร์ผ่านคำขอ ajax บนไคลเอนต์ฉันแสดงข้อความข้อผิดพลาดตาม

อ่านเพิ่มเติม: ข้อผิดพลาดทั้งหมด, เป็นระบบ, สุ่ม:

https://answers.yahoo.com/question/index?qid=20080918203131AAEt6GO


-2

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


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