ถ้าเป็นไปได้อย่าทำอย่างนี้
นั่นคือคำตอบ - เป็นการต่อต้านรูปแบบ หากลูกค้าทราบตารางที่ต้องการข้อมูลจากนั้นSELECT FROM ThatTable
หากลูกค้ารู้ว่าโต๊ะมันต้องการข้อมูลจากแล้วหากฐานข้อมูลได้รับการออกแบบในลักษณะที่จำเป็นดูเหมือนว่าจะได้รับการออกแบบให้เหมาะสมย่อย หากชั้นการเข้าถึงข้อมูลต้องการทราบว่ามีค่าอยู่ในตารางหรือไม่การเขียน SQL ในโค้ดนั้นทำได้ง่ายและการผลักโค้ดนี้ลงในฐานข้อมูลก็ไม่ดี
สำหรับฉันแล้วดูเหมือนว่าการติดตั้งอุปกรณ์ภายในลิฟต์ซึ่งเราสามารถพิมพ์หมายเลขชั้นที่ต้องการได้ หลังจากกดปุ่ม Go แล้วจะเลื่อนมือกลไปยังปุ่มที่ถูกต้องสำหรับชั้นที่ต้องการแล้วกด สิ่งนี้แนะนำปัญหาที่อาจเกิดขึ้นมากมาย
โปรดทราบ: ที่นี่ไม่มีเจตนาล้อเลียน ตัวอย่างลิฟต์โง่ ๆ ของฉันคือ * อุปกรณ์ที่ดีที่สุดที่ฉันสามารถจินตนาการได้ * เพื่อชี้ให้เห็นปัญหาเกี่ยวกับเทคนิคนี้อย่างรวบรัด มันเพิ่มเลเยอร์ของทิศทางที่ไร้ประโยชน์ย้ายตัวเลือกชื่อตารางจากพื้นที่ผู้โทร (โดยใช้ DSL, SQL ที่แข็งแกร่งและเข้าใจดี) ลงในไฮบริดโดยใช้โค้ด SQL ฝั่งเซิร์ฟเวอร์ที่คลุมเครือ / แปลกประหลาด
การแบ่งความรับผิดชอบดังกล่าวผ่านการเคลื่อนย้ายตรรกะการสร้างแบบสอบถามไปยัง SQL แบบไดนามิกทำให้โค้ดเข้าใจยากขึ้น มันละเมิดแบบแผนมาตรฐานและเชื่อถือได้ (วิธีที่แบบสอบถาม SQL เลือกสิ่งที่จะเลือก) ในชื่อของโค้ดที่กำหนดเองที่เต็มไปด้วยข้อผิดพลาด
ต่อไปนี้เป็นประเด็นโดยละเอียดเกี่ยวกับปัญหาที่อาจเกิดขึ้นกับแนวทางนี้:
Dynamic SQL นำเสนอความเป็นไปได้ของการแทรก SQL ที่ยากที่จะจดจำในโค้ดส่วนหน้าหรือโค้ดส่วนหลังเพียงอย่างเดียว (ต้องตรวจสอบร่วมกันเพื่อดูสิ่งนี้)
โพรซีเดอร์และฟังก์ชันที่จัดเก็บไว้สามารถเข้าถึงทรัพยากรที่เจ้าของ SP / ฟังก์ชันมีสิทธิ์ แต่ผู้เรียกใช้ไม่ได้ เท่าที่ฉันเข้าใจโดยไม่ต้องดูแลเป็นพิเศษตามค่าเริ่มต้นเมื่อคุณใช้โค้ดที่สร้างไดนามิก SQL และเรียกใช้ฐานข้อมูลจะเรียกใช้ไดนามิก SQL ภายใต้สิทธิ์ของผู้โทร ซึ่งหมายความว่าคุณจะไม่สามารถใช้ออบเจ็กต์ที่มีสิทธิพิเศษได้เลยหรือคุณต้องเปิดให้กับไคลเอนต์ทั้งหมดเพื่อเพิ่มพื้นที่ผิวของการโจมตีที่อาจเกิดขึ้นกับข้อมูลที่มีสิทธิ์ การตั้งค่า SP / ฟังก์ชันในขณะสร้างเพื่อให้ทำงานเป็นผู้ใช้เฉพาะ (ใน SQL Server EXECUTE AS
) อาจช่วยแก้ปัญหานั้นได้ แต่ทำให้สิ่งต่างๆซับซ้อนมากขึ้น สิ่งนี้ทำให้ความเสี่ยงของการฉีด SQL ที่กล่าวถึงในประเด็นก่อนหน้านี้ทวีความรุนแรงยิ่งขึ้นโดยการทำให้ไดนามิก SQL เป็นเวกเตอร์การโจมตีที่น่าดึงดูดมาก
เมื่อนักพัฒนาต้องเข้าใจว่าโค้ดของแอปพลิเคชันกำลังทำอะไรเพื่อแก้ไขหรือแก้ไขข้อบกพร่องเขาจะพบว่าการเรียกใช้การสืบค้น SQL ที่ถูกต้องเป็นเรื่องยากมาก สามารถใช้ SQL profiler ได้ แต่สิ่งนี้ต้องใช้สิทธิพิเศษและอาจมีผลเสียต่อระบบการผลิต การสืบค้นที่ดำเนินการสามารถบันทึกได้โดย SP แต่จะเพิ่มความซับซ้อนเพื่อประโยชน์ที่น่าสงสัย (ต้องรองรับตารางใหม่การล้างข้อมูลเก่า ฯลฯ ) และค่อนข้างไม่ชัดเจน ในความเป็นจริงแอปพลิเคชั่นบางตัวได้รับการออกแบบมาเพื่อให้นักพัฒนาไม่มีข้อมูลรับรองฐานข้อมูลดังนั้นจึงแทบเป็นไปไม่ได้เลยที่เขาจะเห็นข้อความค้นหาที่ถูกส่งไป
เมื่อเกิดข้อผิดพลาดเช่นเมื่อคุณพยายามเลือกตารางที่ไม่มีอยู่คุณจะได้รับข้อความตามบรรทัด "ชื่อวัตถุที่ไม่ถูกต้อง" จากฐานข้อมูล สิ่งนี้จะเกิดขึ้นเหมือนกันทุกประการไม่ว่าคุณจะเขียน SQL ในส่วนหลังหรือฐานข้อมูล แต่ความแตกต่างก็คือนักพัฒนาที่ไม่ดีบางคนที่พยายามแก้ไขปัญหาระบบจะต้องสะกดลึกลงไปอีกระดับหนึ่งในอีกถ้ำหนึ่งที่อยู่ด้านล่างซึ่ง มีปัญหาอยู่เพื่อเจาะลึกขั้นตอนที่น่าแปลกใจที่ไม่ต้องพยายามหาว่าปัญหาคืออะไร บันทึกจะไม่แสดง "ข้อผิดพลาดใน GetWidget" แต่จะแสดง "ข้อผิดพลาดใน OneProcedureToRuleThemAllRunner" นามธรรมนี้โดยทั่วไปจะทำให้ระบบที่เลวร้ายยิ่ง
ตัวอย่างใน pseudo-C # ของการสลับชื่อตารางตามพารามิเตอร์:
string sql = $"SELECT * FROM {EscapeSqlIdentifier(tableName)};"
results = connection.Execute(sql);
แม้ว่าสิ่งนี้จะไม่สามารถขจัดปัญหาที่เป็นไปได้ทั้งหมดเท่าที่จะเป็นไปได้ แต่ข้อบกพร่องที่ฉันระบุไว้กับเทคนิคอื่น ๆ จะไม่มีอยู่ในตัวอย่างนี้