รูปแบบการแทรก SQL ที่พบบ่อยที่สุดใน PHP คือการหลีกเลี่ยงอักขระที่ไม่มีประโยชน์ รูปแบบการฉีด SQL ที่พบบ่อยที่สุดใน PHP คือการหลบหนีอักขระที่ไม่มีประโยชน์ไปยังคำถามของคุณ

เนื่องจากลักษณะงานของฉัน ฉันจึงต้องดำเนินการตรวจสอบความปลอดภัยของซอร์สโค้ดของเว็บแอปพลิเคชัน
เว็บแอปพลิเคชั่นมากมายและโค้ดมากมาย...

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

มาเริ่มกันเลย

ตัวละครที่ไร้ประโยชน์หลบหนี
พบใน 83% ของเว็บแอปพลิเคชัน PHP ที่เสี่ยงต่อการถูกแทรก SQL
การใช้ฟังก์ชัน Escape สำหรับอักขระเช่น
mysql_escape_string
mysql_real_escape_string
เพิ่มสแลช
โดยไม่มีเครื่องหมายคำพูด ส่วนใหญ่มักปรากฏในพารามิเตอร์ตัวเลข (*_id ทุกชนิด)
ตัวอย่าง
$sql = "เลือกผู้ใช้จากรายการผู้ใช้ WHERE userid=".mysql_real_escape_string($_GET["uid"]);

นี่ดูเหมือนจะเป็นรหัสที่ปลอดภัย แต่อยู่เพียงผิวเผินเท่านั้น รูปแบบการฉีด SQL ที่พบบ่อยที่สุดใน PHP ในทางปฏิบัติของฉันพุ่งเข้ามาที่นี่ ในการโจมตีช่องโหว่นี้ ผู้โจมตีจำเป็นต้องหลีกเลี่ยงการใช้อักขระ " " \x00 \r \n \x1a ในเวกเตอร์การโจมตี
ตัวอย่างเช่น:
/index.php?uid=-777 UNION เลือกรหัสผ่านจากรายการผู้ใช้

ค้นหาในรหัส
ซับซ้อนด้วยความหมายของภาษา สำหรับการค้นหาแบบง่ายคุณสามารถใช้ egrep:
egrep -Rin "(select|update|insert|delete|replace).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" . - grep -v "[\""]["\"]"

ตรรกะของนิพจน์การค้นหามีดังนี้: ค้นหาบรรทัดทั้งหมดที่ไม่มีลำดับอักขระเครื่องหมายคำพูด ("", "", "", "") ทางด้านซ้ายของฟังก์ชันการกรอง แน่นอนว่าวิธีนี้ยังห่างไกลจาก 100% แต่เป็นไปไม่ได้ที่จะต้องใช้นิพจน์ทั่วไปเพื่อทำการวิเคราะห์เชิงความหมาย
เพื่อให้ง่ายต่อการแสดงข้อมูล คุณสามารถเน้นฟังก์ชั่นเป็นสีในคอนโซลได้:
egrep -Rin "(select|update|insert|delete|replace).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" . - grep -v "[\""]["\"]" | egrep --color "(mysql_escape_string|mysql_real_escape_string|addslashes)"

เพื่อป้องกันช่องโหว่ไวด์การ์ด ควรใช้การคัดเลือกประเภท
ซึ่งทำงานได้เร็วกว่าและเชื่อถือได้มากกว่าการกรองและการคัดกรองทุกประเภท
สำหรับตัวอย่างข้างต้น แพตช์อาจเป็นดังนี้:
$sql = "เลือกผู้ใช้จากรายชื่อผู้ใช้ WHERE userid=".intval($_GET["uid"]);

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


ก่อนอื่น อธิบายเล็กน้อยว่าทำไมโดยทั่วไปจึงต้องใช้เครื่องหมายทับเหล่านี้
หากเราแทนที่ข้อมูลใดๆ ลงในแบบสอบถาม ดังนั้นเพื่อแยกแยะข้อมูลนี้จากคำสั่ง SQL จะต้องใส่เครื่องหมายคำพูดเพื่อแยกความแตกต่างระหว่างข้อมูลนี้
เช่น ถ้าคุณเขียน
SELECT * จากตาราง โดยที่ชื่อ = บิล
จากนั้นฐานข้อมูลจะตัดสินว่า Bill เป็นชื่อของเขตข้อมูลอื่น ไม่พบ และจะส่งข้อผิดพลาด ดังนั้นข้อมูลที่ถูกแทนที่ (ในกรณีนี้คือชื่อ Bill) จะต้องอยู่ในเครื่องหมายคำพูด - จากนั้นฐานข้อมูลจะพิจารณาว่าเป็นสตริงซึ่งจะต้องกำหนดค่าให้กับฟิลด์ชื่อ:
SELECT * จากตาราง WHERE name = "Bill"
อย่างไรก็ตาม ราคาอาจปรากฏในข้อมูลด้วย ตัวอย่างเช่น,
SELECT * จากตารางโดยที่ name = "D"Artagnan"
ที่นี่ฐานข้อมูลจะตัดสินว่า "D" คือข้อมูล และ Artagnan เป็นคำสั่งที่ไม่ทราบ และจะทำให้เกิดข้อผิดพลาดด้วย ดังนั้นจึงจำเป็นต้องติดตามข้อมูลทั้งหมดเพื่ออธิบายให้ฐานข้อมูลทราบว่าเครื่องหมายคำพูด (และอักขระพิเศษอื่น ๆ) ที่พบในนั้นอ้างอิงถึงข้อมูล
ด้วยเหตุนี้ เราจะได้รับคำขอที่ถูกต้องซึ่งจะไม่ทำให้เกิดข้อผิดพลาด:
SELECT * จากตาราง โดยที่ name = "D\"Artagnan"

ดังนั้นเราจึงพบว่าเมื่อทำการแทนที่ข้อมูลลงในแบบสอบถาม ควรปฏิบัติตามกฎสองข้อ:
- ข้อมูลทั้งหมดที่แทรกลงในคำขอจะต้องอยู่ในเครื่องหมายคำพูด (เดี่ยวหรือคู่ แต่ข้อมูลเดี่ยวจะสะดวกกว่าและใช้บ่อยกว่า)
- ในตัวแปรสตริงทั้งหมด จะต้องยกเว้นอักขระพิเศษด้วยเครื่องหมายทับ

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

ที่จริงแล้ว สิ่งที่กล่าวมาทั้งหมดใช้กับข้อมูลสตริงและวันที่ สามารถแทรกตัวเลขได้โดยไม่ต้องต่อท้ายหรือล้อมรอบด้วยเครื่องหมายคำพูด ถ้าคุณทำเช่นนี้แล้ว จำเป็น!บังคับข้อมูลให้เป็นประเภทที่ต้องการก่อนที่จะแทรกลงในแบบสอบถาม เช่น
$id = intval ($id);
อย่างไรก็ตาม เพื่อความเรียบง่าย (และความน่าเชื่อถือ) คุณสามารถทำงานกับตัวเลขได้เช่นเดียวกับสตริง (เนื่องจาก mysql ยังคงแปลงเป็นประเภทที่ต้องการ) ดังนั้น เราจะติดตามข้อมูลใด ๆ ที่แทรกลงในคำขอและใส่ไว้ในเครื่องหมายคำพูด

นอกจากนี้ยังมีกฎอีกข้อหนึ่ง - เป็นทางเลือก แต่ควรปฏิบัติตามเพื่อหลีกเลี่ยงข้อผิดพลาด:
ชื่อของฟิลด์และตารางควรอยู่ในเครื่องหมายคำพูดเดี่ยวด้านหลัง - "`" (คีย์ที่มีสัญลักษณ์นี้จะอยู่บนแป้นพิมพ์มาตรฐานทางด้านซ้ายของคีย์ "1") ท้ายที่สุดชื่อฟิลด์อาจตรงกับ mysql คำหลัก แต่ถ้าเราใช้เครื่องหมายคำพูดย้อนกลับ MySQL จะเข้าใจทุกอย่างถูกต้อง:
SELECT * จาก `ตาราง` โดยที่ `date` = "2006-04-04"
คุณควรแยกความแตกต่างระหว่างเครื่องหมายคำพูดเหล่านี้ และไม่สับสนระหว่างเครื่องหมายคำพูดกับเครื่องหมายอื่นๆ คุณควรจำไว้ว่า backticks จะไม่ถูกหลบเลี่ยงด้วยเครื่องหมายทับ

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

SQL Injection เป็นวิธีการโจมตีของแฮ็กเกอร์เมื่อข้อมูลที่ถ่ายโอนไปยังสคริปต์ได้รับการแก้ไขในลักษณะที่แบบสอบถามที่สร้างในสคริปต์นี้เริ่มดำเนินการบางอย่างที่แตกต่างไปจากที่ตั้งใจไว้โดยสิ้นเชิง
กฎสำหรับการป้องกันการโจมตีดังกล่าวสามารถแบ่งออกเป็นสองจุด:
1. การทำงานกับข้อมูล
2. การทำงานกับการควบคุมแบบสอบถาม

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

จุดที่สองนั้นยากกว่ามากเนื่องจากไม่มีกฎสากลสำหรับข้อมูล - backticks จะไม่ปกป้องชื่อฟิลด์จากการถูกแฮ็กเกอร์แก้ไข ไม่สามารถใช้เครื่องหมายคำพูดเพื่อป้องกันชื่อตาราง คำสั่ง SQL พารามิเตอร์คำสั่ง LIMIT และคำสั่งอื่น ๆ
ดังนั้นกฎพื้นฐานเมื่อแทนที่องค์ประกอบควบคุมลงในแบบสอบถามคือ:
หากคุณต้องการแทรกคำสั่ง SQL หรือชื่อของเขตข้อมูล ฐานข้อมูล ตารางลงในแบบสอบถามแบบไดนามิก คุณไม่ควรแทรกคำสั่งเหล่านั้นลงในแบบสอบถามโดยตรงไม่ว่าในกรณีใด
ตัวเลือกทั้งหมดสำหรับการเพิ่มเติมดังกล่าวจะต้องเขียนเป็น ADVANCE ในสคริปต์ของคุณ และเลือกตามสิ่งที่ผู้ใช้ป้อน
ตัวอย่างเช่น หากคุณต้องการส่งชื่อฟิลด์ไปยังคำสั่งซื้อตามตัวดำเนินการ คุณไม่ควรแทนที่โดยตรงไม่ว่าในกรณีใดก็ตาม เราต้องตรวจสอบก่อน ตัวอย่างเช่น สร้างอาร์เรย์ของค่าที่ถูกต้อง และแทนที่ลงในคำขอเฉพาะเมื่อมีพารามิเตอร์ที่ส่งผ่านอยู่ในอาร์เรย์นี้:
$orders =array("name" , "price" , "qty" );
$key = array_search($_GET["sort"], $orders));
$orderby = $คำสั่งซื้อ [ $key ];
$แบบสอบถาม= "เลือก * จาก `ตาราง` เรียงตาม $orderby";
เราค้นหาอาร์เรย์ของตัวเลือกที่อธิบายไว้ล่วงหน้าสำหรับคำที่ผู้ใช้ป้อน และหากพบ เราจะเลือกองค์ประกอบที่เกี่ยวข้องของอาร์เรย์ หากไม่พบรายการที่ตรงกัน องค์ประกอบแรกของอาร์เรย์จะถูกเลือก
ดังนั้นสิ่งที่แทนที่ในคำขอจึงไม่ใช่สิ่งที่ผู้ใช้ป้อน แต่เป็นสิ่งที่เขียนไว้ในสคริปต์ของเรา
ต้องทำเช่นเดียวกันในกรณีอื่น ๆ ทั้งหมด
ตัวอย่างเช่น ถ้าส่วนคำสั่ง WHERE ถูกสร้างขึ้นแบบไดนามิก:
ถ้า (!empty($_GET [ "price" ])) $where .= "price="" . mysql_real_escape_string ($_GET [ "price" ]). """ ;
$แบบสอบถาม= "เลือก * จาก `ตาราง` โดยที่ $ ที่ไหน";
เป็นเรื่องยากสำหรับฉันที่จะจินตนาการถึงกรณีที่ชื่อตารางสามารถแทรกลงในคิวรีแบบไดนามิกได้ แต่หากเกิดเหตุการณ์เช่นนี้ จะต้องแทรกชื่อจากชุดที่กำหนดไว้ล่วงหน้าในสคริปต์เท่านั้น
พารามิเตอร์ของตัวดำเนินการ LIMIT ควรถูกบังคับให้เป็นประเภทจำนวนเต็มโดยใช้การดำเนินการทางคณิตศาสตร์หรือฟังก์ชัน intval()
อย่าคิดว่าตัวอย่างที่แสดงไว้ที่นี่ใช้ตัวเลือกทั้งหมดสำหรับการสร้างคิวรีแบบไดนามิก คุณเพียงแค่ต้องเข้าใจหลักการและนำไปใช้ในกรณีดังกล่าวทั้งหมด

คุณสมบัติของการทำงานร่วมกับตัวดำเนินการ LIKE
กรณีที่แยกจากกันโดยสิ้นเชิงคือตัวดำเนินการ LIKE
ประการแรก นอกเหนือจากการติดตามตามปกติแล้ว เครื่องหมายทับจะต้องเพิ่มเป็นสองเท่าในตัวแปรที่แทนที่ใน LIKE นั่นคือหากตัวแปรมีอักขระ \ จะต้องเพิ่มเป็นสองเท่า จากนั้นการติดตามตามปกติจะต้องดำเนินการผ่าน mysql_real_escape_string
เช่น ถ้าเรากำลังมองหาสตริง
อักขระ \ เรียกว่า "แบ็กสแลช" และเราต้องการการจับคู่แบบตรงทั้งหมด จากนั้นเราก็ใช้ mysql_real_escape_string และการสืบค้นเป็นแบบมาตรฐาน:
SELECT * FROM test WHERE field = "สัญลักษณ์ \\ เรียกว่า \"แบ็กสแลช\""หากเราต้องการแทนที่สตริงนี้ใน LIKE ก่อนอื่นเราต้องแทนที่แต่ละเครื่องหมายทับด้วยสอง จากนั้นจึงใช้ mysql_real_escape_string ผลลัพธ์ที่ได้ก็จะเป็น
SELECT * จากตาราง โดยที่ฟิลด์ LIKE "% character \\\\ เรียกว่า \"backslash\"%"
สิ่งที่สองที่ควรทราบก็คือ ไม่มีฟังก์ชันใดที่เพิ่มเครื่องหมายทับเพิ่มลงในเมตาอักขระการค้นหา "%" และ "_" ที่ใช้ในตัวดำเนินการ LIKE ดังนั้น หากคุณใช้โอเปอเรเตอร์นี้และไม่ต้องการให้อักขระ _ และ % ใช้เป็นไวด์การ์ด ให้เพิ่มเครื่องหมายทับด้วยตนเอง ซึ่งสามารถทำได้ด้วยคำสั่ง
$data = addCslashes($data, "%_");

คำเตือน - นี่ไม่ใช่การติดขนตา! ชื่อฟังก์ชันนี้มี "c" พิเศษอยู่ในชื่อ
ดังนั้นปรากฎว่าเราต้องประมวลผลตัวแปรที่ใช้ในตัวดำเนินการ LIKE แยกกัน
ขั้นแรกให้แทนที่หนึ่งสแลชด้วยสอง โดยใช้ตัวอย่างโค้ดดังนี้:
$var = str_replace ("\\" , "\\\\" , $var );จากนั้น (คุณสามารถติดตามข้อมูลอื่น ๆ ทั้งหมดในคำขอ):
$var = mysql_real_escape_string ($var);
แล้วถ้าเราต้องการให้ _ และ % ตรงกันทุกประการ เราก็ทำ
$var = addCslashes($var, "_%");ดังนั้น ถ้าเราค้นหา เช่น สำหรับสตริงต่อไปนี้
อักขระ \ เรียกว่า "แบ็กสแลช" และอักขระ _ เรียกว่า "ขีดล่าง"หลังจากประมวลผลแล้ว ในคำขอควรมีลักษณะดังนี้:

"%สัญลักษณ์ \\\\ เรียกว่า \"แบ็กสแลช\" และสัญลักษณ์ \_ เรียกว่า \"ขีดเส้นใต้\"
นั่นคือเครื่องหมายสแลชซึ่งเดิมอยู่ในบรรทัดนั้นเพิ่มขึ้นสี่เท่า ตัวละครที่เหลือก็ติดตามตามปกติ บวก - มองเห็นอักขระขีดล่างได้
เกี่ยวกับเครื่องหมายทับ วิธีกำจัดพวกเขา
เครื่องหมายทับหรือแบ็กสแลชจากแบ็กสแลชภาษาอังกฤษคือแบ็กสแลช (“\”) ที่ปรากฏขึ้นในตัวแปรของคุณอย่างอธิบายไม่ถูก มันถูกเพิ่มเข้าไปในอักขระพิเศษบางตัว แต่ส่วนใหญ่จะสังเกตเห็นได้เนื่องจากเครื่องหมายคำพูด

สิ่งนี้เกิดขึ้นเนื่องจากการตั้งค่า PHP พิเศษ ซึ่งโดยปกติจะเปิดใช้งานตามค่าเริ่มต้นบนโฮสติ้ง ตามทฤษฎีแล้ว การตั้งค่าเหล่านี้สามารถเพิ่มความปลอดภัยของสคริปต์ที่ทำงานกับฐานข้อมูลได้ ในทางปฏิบัติ การเพิ่มเครื่องหมายทับโดยอัตโนมัติมักส่งผลให้เกิดความสับสนและความไม่สะดวก ทั้งเมื่อทำงานกับฐานข้อมูลและในกรณีที่ไม่มีฐานข้อมูล
ด้านล่างนี้เราจะตรวจสอบทั้งสองกรณีโดยละเอียด
คำสั่ง php.ini ซึ่งเรียกรวมกันว่า "ราคาวิเศษ" มีหน้าที่เพิ่มเครื่องหมายทับโดยอัตโนมัติ:

หากคุณทำงานโดยไม่มีฐานข้อมูลหรือทำงานกับฐานข้อมูลอย่างถูกต้อง (ซึ่งจะกล่าวถึงด้านล่าง) เครื่องหมายทับพิเศษจะรบกวนคุณเท่านั้น และคุณต้องกำจัดมันทิ้ง วิธีที่ง่ายและถูกต้องที่สุดคือปิดการใช้งานการเพิ่มอัตโนมัติในการตั้งค่า PHP
ซึ่งสามารถทำได้โดยการแก้ไขคำสั่งที่เกี่ยวข้องใน php.ini หากคุณสามารถเข้าถึงได้ หรือโดยการสร้างไฟล์ .htaccess ในไดเร็กทอรีสุดท้ายของไซต์และเพิ่มบรรทัดลงไป
php_flag magic_quotes_gpc 0
php_flag magic_quotes_runtime 0

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

วิธีที่ง่ายที่สุดในการทำความเข้าใจข้อมูลที่ได้รับระหว่างการดำเนินการคือการเขียนที่จุดเริ่มต้นของสคริปต์:
set_magic_quotes_runtime(0);

  • สำหรับข้อมูลที่ได้รับจากผู้ใช้ทุกอย่างจะซับซ้อนกว่ามาก สำหรับโค้ดนี้เราต้องการสองฟังก์ชัน:
  • คุณสามารถตรวจสอบว่า PHP ได้เพิ่มเข้าไปหรือไม่โดยใช้ฟังก์ชัน get_magic_quotes_gpc
    ฟังก์ชั่นแถบสแลชจะลบเครื่องหมายสแลชออก
    ดังนั้น คุณต้องตรวจสอบโดยใช้อันแรก และหากเพิ่ม PHP แล้ว ให้ตรวจสอบตัวแปรขาเข้าทั้งหมดและล้างตัวแปรเหล่านั้นโดยใช้อันที่สอง
    หากคุณทำงานอย่างถูกต้องด้วย register_globals = off ก็เพียงพอที่จะใช้แถบสแลชกับอาร์เรย์ทั้งหมดที่มีข้อมูลที่มาจากเบราว์เซอร์
    ตัวอย่างเช่น คุณสามารถรวมโค้ดต่อไปนี้ในสคริปต์ไซต์ทั้งหมด:
    แถบฟังก์ชั่น (& $el ) (
    ถ้า (is_array($el))
    foreach($el เป็น $k => $v )
    แถบ($el[$k]);
    }
    อื่น $el = แถบสแลช ($el );
    ถ้า (get_magic_quotes_gpc()) (
    แถบ($_GET);
    แถบ($_POST);
    แถบ ($_COOKIE);
    แถบ($_REQUEST);
    ถ้า (isset($_SERVER [ "PHP_AUTH_USER" ])) แถบ ($_SERVER [ "PHP_AUTH_USER" ]);
    }
    ถ้า (isset($_SERVER [ "PHP_AUTH_PW" ])) แถบ ($_SERVER [ "PHP_AUTH_PW" ]);

    ในกรณีที่การตั้งค่า register_globals ไม่ถูกต้องจะหาวิธีแก้ปัญหาที่ยอมรับได้ยากดังนั้นจึงเป็นการดีกว่า - ฉันขอย้ำ - ทำงานกับการตั้งค่าที่ถูกต้องทันที

    • หมายเหตุ สาเหตุหนึ่งที่คุณไม่ควรเชื่อถือ "คำพูดวิเศษ" เป็นอีกสาเหตุหนึ่ง ไม่น่าเป็นไปได้มาก แต่ก็ยังอยู่ "คำพูดวิเศษ" จริงๆ แล้วไม่ได้หมายถึงสองคำสั่ง แต่หมายถึงสามคำสั่ง อันที่สามคือ magic_quotes_sybase ไม่เพียงแต่จะเพิ่มเครื่องหมายคำพูดแทนเครื่องหมายสแลชเท่านั้น แต่ยังยกเลิกเอฟเฟกต์ของ magic_quotes_gpc ด้วย หากโดยปาฏิหาริย์ทั้งสองคำสั่งนี้มีสถานะเป็น "เปิด" แสดงว่าคำสั่งสุดท้ายนั่นคือโดยการใช้ "เครื่องหมายคำพูดวิเศษ" ในกรณีนี้ เราจะได้รับความพึงพอใจจากข้อความค้นหาที่เขียนไม่ถูกต้อง โดยทั่วไป ตามทฤษฎีแล้ว เราต้องคำนึงถึงการมีอยู่ของคำสั่งนี้ เนื่องจากมันยังสร้างความประหลาดใจ เช่น... การเปลี่ยนแปลงพฤติกรรมของฟังก์ชัน addslashes และ stripslashes! หาก magic_quotes_sybase = on ฟังก์ชันเหล่านี้จะเริ่มเพิ่มและลบเครื่องหมายคำพูดเดี่ยวแทนที่จะเป็นเครื่องหมายทับ ตามลำดับ
    • ตัวอย่างทั้งหมดที่ให้ไว้เกี่ยวข้องกับฐานข้อมูล Mysql เท่านั้น กฎเฉพาะสำหรับการเขียนคำสั่งอาจแตกต่างกันสำหรับ DBMS อื่นๆ แต่หลักการทั่วไปยังคงเหมือนเดิม:
      • หากมี API สำหรับการทำงานกับฐานข้อมูลหรือไลบรารีบุคคลที่สามให้บริการ ฟังก์ชั่นพิเศษสำหรับการเขียนแบบสอบถามและมีความเป็นไปได้ที่จะใช้มันคุณต้องใช้มันก่อน
      • หากไม่มีฟังก์ชันดังกล่าว คุณควรดูในเอกสารประกอบสำหรับฟังก์ชันสำหรับการ Escape อักขระพิเศษสำหรับ DBMS นี้
    หมายเหตุ: แบบฟอร์ม
    เมื่อแสดงค่าในแท็กอินพุตของแบบฟอร์ม เครื่องหมายทับไม่ได้ช่วยอะไร
    หากต้องการแสดงข้อความทั้งหมดในช่องดังกล่าว ค่าจะต้องอยู่ในเครื่องหมายคำพูดและไปยังข้อมูลเอาท์พุต ใช้ฟังก์ชัน htmlspecialchars()
    ตัวอย่าง:

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

    1. คำชี้แจงที่เตรียมไว้
    2. ใช้ _real_escape_string()
    3. ไม่ใช้เครื่องหมายอัญประกาศวิเศษเพราะมันสร้างความสับสนให้กับฐานข้อมูลและจบลงด้วยการให้ข้อมูลเช่น "คุณไม่ได้เรียกมันว่า..."

    ทั้งหมดนี้ยอดเยี่ยมมากและฉันก็คอยจับตาดูมันอยู่ อย่างไรก็ตาม ฉันสงสัยว่าตัวละครอย่างเครื่องหมายดอลลาร์ [$] เครื่องหมายเปอร์เซ็นต์ [%] และบางทีตัวละครอื่นๆ ควรหลบหนีออกไปหรือไม่ แบบสอบถามอาจตีความเครื่องหมายดอลลาร์ว่าเป็นตัวแปร PHP ได้หรือไม่ แล้วไวยากรณ์ LIKE ที่ฉันได้ยินมาใช้สัญลักษณ์ % หรือแม้แต่ไวด์การ์ดล่ะ ข้อความที่เตรียมไว้ควรดูแลเรื่องทั้งหมดนี้ในทางเทคนิค แต่ฉันแค่อยากจะรักษาความปลอดภัยและให้แน่ใจว่าฉันได้ทำทุกอย่างอย่างเหมาะสม ในกรณีที่ฉันลืมใช้ข้อความที่เตรียมไว้หรือละเลยฉันหวังว่าแนวป้องกันที่สองนี้จะบอกฉันว่าฉันสามารถหายวิงเวียนศีรษะได้

    นี่คือสิ่งที่ฉันใช้ในการหลบหนี:

    ฟังก์ชั่น Escape($connection, $data)( $new_data = trim($data); $new_data = i_real_escape_string($connection, $new_data); $new_data = addcslashes($new_data, "%_$"); $new_data = htmlspecialchars ($new_data, ENT_NOQUOTES); ส่งคืน $new_data;

    แล้วนี่ถูกต้องไหม? ฉันกำลังทำอะไรผิดมหันต์หรือเปล่า? โปรดทราบว่าเมื่อส่งคืนข้อมูลฐานข้อมูล ฉันจะต้องลบแบ็กสแลชที่อยู่หน้าอักขระ $,% และ _

    ฉันกำลังทำอะไรผิดมหันต์หรือเปล่า?

    ก่อนอื่นเกี่ยวกับการวิจัยของคุณ

    แถลงการณ์ที่เตรียมไว้ – คนเดียวเท่านั้นสิ่งมหัศจรรย์ที่คุณพบ

    แม้ว่าการใช้ mysqli_real_escape_string (สมมติว่าคุณกำลังใช้คำสั่งที่เตรียมไว้) ก็จะเป็นเช่นนั้น ไร้ประโยชน์และเป็นอันตราย(สร้างผลลัพธ์ที่คุณสังเกตตัวเอง: "คุณเรียกว่าไม่ใช่\t...")

    และ Magic Quotes ก็ถูกลบออกจากภาษาไปนานแล้ว - ดังนั้นจึงไม่คุ้มค่าอะไรเลย

    ดังนั้นแม้แต่สถานที่เริ่มแรกของคุณส่วนใหญ่ยังผิดอย่างชัดเจน

    ตอนนี้ถึงคำถามของคุณ

    แบบสอบถามอาจตีความเครื่องหมายดอลลาร์ว่าเป็นตัวแปร PHP ได้หรือไม่

    แล้วไวยากรณ์ LIKE ที่ฉันได้ยินมาใช้สัญลักษณ์ % หรือแม้แต่ไวด์การ์ดล่ะ

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

    ทุกครั้งที่คุณจะใช้ตัวดำเนินการ LIKE คุณต้องตัดสินใจว่าจะใช้อักขระตัวใดและตัวใดที่จะไม่อนุญาตให้ใช้ คุณไม่สามารถใช้โซลูชันแบบครั้งเดียวได้ ไม่ต้องพูดถึงว่าในการโต้ตอบ mysql อื่นๆ ทั้งหมด เครื่องหมาย % ไม่มีความหมายพิเศษ

    ข้อความที่เตรียมไว้ควรดูแลเรื่องทั้งหมดนี้ในทางเทคนิค

    ข้อความที่เตรียมไว้ไม่เกี่ยวข้องกับเครื่องหมาย $ หรือ % คำสั่งที่เตรียมไว้อ้างถึงการฉีด SQL แต่ไม่มีอักขระใดที่สามารถทำให้เกิดสิ่งนี้ได้ (คุณไม่สามารถเรียกว่า "การฉีด" ซึ่งเป็นตัวดำเนินการ LIKE ที่ใช้อย่างถูกต้องใช่ไหม)

    สุดท้ายก็ถึงส่วนที่แย่ที่สุด

    ในกรณีที่คุณลืมใช้ข้อความที่เตรียมไว้หรือละเลยที่จะปฏิบัติตาม

    ไม่มีอะไรจะช่วยคุณได้

    และความช่วยเหลือน้อยที่สุดก็จะมาจากฟังก์ชันที่คุณพัฒนาขึ้น

    สรุป.

    1. กำจัดคุณสมบัตินี้
    2. ใช้ ฟิลเลอร์ *เพื่อแสดงตัวแปรแต่ละตัวในแบบสอบถาม
    3. ยกเว้นอักขระ % และ _ ในอินพุตเฉพาะในกรณีที่จะใช้ในตัวดำเนินการ LIKE และคุณไม่ต้องการให้ตีความอักขระเหล่านั้น
    4. ใช้ htmlspecialchars() สำหรับเอาต์พุต ไม่ใช่อินพุต mysql

    *อ่านข้อความที่เตรียมไว้หากคำนี้ไม่คุ้นเคยกับคุณ

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

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

    คุณไม่จำเป็นต้องใช้ htmlspecialchars เมื่อเข้าถึงฐานข้อมูล ควรใช้เมื่อแสดงข้อมูลต่อผู้ใช้ในหน้า HTML เท่านั้น เพื่อป้องกันการแทรก XSS

    ขึ้นอยู่กับว่าข้อมูลอะไรและใช้เพื่ออะไร

    หากคุณพบว่าคำสั่งเริ่มต้นของ PHP มีขนาดใหญ่และซับซ้อนเกินไป ฉันขอแนะนำให้ดูคลาสบางคลาสที่มีอยู่บน GitHub เพื่อให้คุณเห็นภาพของการสืบค้นแบบง่าย

    ตัวอย่างการแทรกคำสั่งในคลาสนี้

    $data = Array ("login" => "admin", "active" => true, "firstName" => "John", "lastName" => "Doe", "password" => $db->func( "SHA1(?)",Array ("รหัสผ่านลับ+เกลือ")), // รหัสผ่าน = SHA1("รหัสผ่านลับ+เกลือ") "createdAt" => $db->now(), // createAt = NOW() " หมดอายุ" => $db->ตอนนี้("+1Y") // หมดอายุ = NOW() + ช่วงเวลา 1 ปี // ช่วงเวลาที่สนับสนุน [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear); $id = $db->insert("ผู้ใช้", $data); if ($id) echo "สร้างผู้ใช้แล้ว Id=" $รหัส; อย่างอื่นสะท้อน "การแทรกล้มเหลว: " $db->getLastError();

    สตริงเครื่องหมายคำพูด (11)

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

    $query = "ใส่ค่าลงในตาราง (id, col1, col2) (NULL, val1, val2)";

    นอกจากนี้ ในตัวอย่างข้างต้น ให้พิจารณาว่า "ตาราง" "col[n]" และ "val[n]" สามารถเป็นตัวแปรได้

    มาตรฐานเรื่องนี้คืออะไร? คุณกำลังทำอะไร?

    ฉันอ่านคำตอบสำหรับคำถามที่คล้ายกันมาประมาณ 20 นาทีแล้ว แต่ดูเหมือนจะไม่มีคำตอบที่แน่ชัดสำหรับคำถามนี้

    คำตอบ

    ตอนนี้สมมติว่าคุณกำลังใช้ตัวแปรโพสต์โดยตรงในการสืบค้น MySQL จากนั้นใช้ดังนี้:

    $query = "INSERT INTO `table` (`id`, `name`, `email`) ค่า (" ".$_POST["id"]." ", " ".$_POST["name"]" "," ".$_POST["อีเมล"]" ")";

    นี่คือแนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ตัวแปร PHP ใน MySQL

    ส่วนใหญ่อยู่ใน Mysql ตัวระบุประเภทนี้จะใช้ในการสืบค้น ` , " , " และ ()

      " หรือ " ใช้เพื่อรวมสตริงเป็นค่า "01/26/2014 00:00:00" หรือ "01/26/2014 00:00:00" ตัวระบุนี้ใช้สำหรับฟังก์ชันสตริง "01/26/2014 00:00:00" เท่านั้น เช่น now() หรือ sum ,max

      ` ใช้เพื่อรวมตารางหรือตารางเช่นเลือก column_name จาก table_name โดยที่ id = "2"

      () ใช้เพื่อล้อมรอบบางส่วนของแบบสอบถามเท่านั้น เช่น เลือก column_name จาก table_name โดยที่ (id = "2" และ sex = "male") หรือ name = "rakesh

    นอกเหนือจากคำตอบทั้งหมด (ที่อธิบายไว้อย่างดี) แล้ว ก็ไม่มีการกล่าวถึงด้านล่างนี้เลย และฉันก็มักจะเข้ามาถามตอบนี้บ่อยๆ

    โดยสรุป; MySQL คิดว่าคุณต้องการทำคณิตศาสตร์บนโต๊ะ/คอลัมน์ของคุณเอง และตีความเครื่องหมายยัติภังค์ เช่น "email" เป็น e mail

    ข้อสงวนสิทธิ์ดังนั้นฉันคิดว่าฉันจะเพิ่มสิ่งนี้เป็นคำตอบ "FYI" สำหรับผู้ที่ยังใหม่กับการทำงานกับฐานข้อมูลและอาจไม่เข้าใจคำศัพท์ทางเทคนิคที่อธิบายไว้แล้ว

    (มีคำตอบที่ดีด้านบนเกี่ยวกับลักษณะ SQL ของคำถามของคุณ แต่สิ่งนี้อาจเกี่ยวข้องหากคุณยังใหม่กับ PHP)

    อาจเป็นสิ่งสำคัญที่ต้องทราบว่า PHP ถือว่าราคาเดี่ยวและคู่ต่างกัน...

    สตริงเครื่องหมายคำพูดเดี่ยวถือเป็น "ตัวอักษร" และเป็นสตริงแบบ WYSIWYG จำนวนมาก สตริงที่มีเครื่องหมายคำพูดคู่ถูกตีความโดย PHP เพื่อการแทนที่ตัวแปรที่เป็นไปได้ (การอ้างอิงกลับใน PHP ไม่ใช่สตริงที่แน่นอน แต่จะรันคำสั่งในเชลล์และส่งกลับผลลัพธ์)

    $foo = "บาร์"; echo "มี $foo"; // มี $foo echo "มี $foo"; // มีแถบเสียงสะท้อน `ls -l`; // ... รายการไดเร็กทอรี

    หากตารางและค่า cols เป็นตัวแปร แสดงว่ามีสองวิธี:

    ด้วยเครื่องหมายคำพูดคู่ "" ข้อความค้นหาที่สมบูรณ์คือ:

    $query = "ใส่เข้าไปใน $table_name (id, $col1, $col2) ค่า (NULL, "$val1", "$val2"");

    $query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.") ค่า (NULL, "".$val1.", "".$val2."" ) ";

    ด้วยเครื่องหมายคำพูดเดี่ยว "" :

    $query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.") ค่า (NULL, ".$val1.", ".$val2.")";

    ใช้ backticks `` เมื่อชื่อคอลัมน์/ค่าคล้ายกับคีย์เวิร์ดที่สงวนไว้ของ MySQL

    บันทึก.หากคุณระบุชื่อคอลัมน์ด้วยชื่อตาราง ให้ใช้ backticks ดังนี้:

    `ชื่อตาราง` . `คอลัมน์_ชื่อ`<- Примечание: исключить. из задних клещей.

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

    ควรใช้เครื่องหมายคำพูดเดี่ยวสำหรับค่าสตริง เช่น ในรายการ VALUES() เครื่องหมายคำพูดคู่ได้รับการสนับสนุนโดย MySQL สำหรับค่าสตริงเช่นกัน แต่เครื่องหมายคำพูดเดี่ยวได้รับการยอมรับอย่างกว้างขวางมากขึ้นจาก RDBMS อื่นๆ ดังนั้นจึงเป็นความคิดที่ดีที่จะใช้เครื่องหมายคำพูดเดี่ยวแทนเครื่องหมายคำพูดคู่

    MySQL ยังคาดว่าค่า DATE และ DATETIME ตามตัวอักษรจะเป็นเครื่องหมายคำพูดเดี่ยวเป็นสตริง เช่น "2001-01-01 00:00:00" สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารประกอบวันที่และเวลา โดยเฉพาะอย่างยิ่งทางเลือกอื่นนอกเหนือจากการใช้ยัติภังค์ - เป็นตัวคั่นเซ็กเมนต์ในสตริงวันที่

    ดังนั้นเมื่อใช้ตัวอย่างของคุณ ฉันจะส่งสตริง PHP สองครั้งและใช้เครื่องหมายคำพูดเดี่ยวสำหรับค่า "val1", "val2" NULL เป็นคีย์เวิร์ด MySQL และไม่ใช่ค่า ดังนั้นจึงไม่ได้ใช้

    ตัวระบุตารางหรือคอลัมน์เหล่านี้ไม่มีคำสงวนหรือใช้อักขระที่ต้องมีเครื่องหมายคำพูด แต่ฉันยังคงยกมาด้วยเอาต์พุตแบบย้อนกลับ (เพิ่มเติมในภายหลัง...)

    ไม่ควรอ้างอิงฟังก์ชันที่เกี่ยวข้องกับ RDBMS (เช่น NOW() ใน MySQL) แม้ว่าอาร์กิวเมนต์จะอยู่ภายใต้กฎเดียวกันหรือกฎการเสนอราคาที่กล่าวถึงไปแล้วก็ตาม

    Backtick (`) ตาราง & คอลัมน์ ─┬──── ┬──┬───────┐ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ $query = " INSERT INTO `table` (`id`, `col1`, `col2`, `date`, `updated`) ค่า (NULL, "val1", "val2", "2001-01-01", NOW())"; คำหลักที่ไม่มีเครื่องหมายคำพูด ─────┴┴┴┘ │ │ │ │ │ │ │││││ สตริงเครื่องหมายคำพูดเดี่ยว (") ───────────┴─ ───┴── ┴────┘ │ │ │││││ ยกมาเดี่ยว (") วันที่ ──────────────────────── ────┴── ฟังก์ชั่นที่ไม่ได้ใส่เครื่องหมายคำพูด ──────────────────────── ────────── ───────┴┴┴┴┘

    การแก้ไขตัวแปร

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

    // สิ่งเดียวกันกับการแทนที่ตัวแปรบางตัว // ในที่นี้ ชื่อตารางตัวแปร $table เป็นแบบ backtick-quoted และตัวแปร // ในรายการ VALUES เป็นแบบ single-quoted $query = "INSERT INTO `$ตาราง`(`id`, `col1`, `col2`, `date`) ค่า (NULL, "$val1", "$val2", "$วันที่")";

    คำชี้แจงที่เตรียมไว้

    เมื่อทำงานกับคำสั่งที่เตรียมไว้ ให้อ่านเอกสารประกอบเพื่อพิจารณาว่าควรรวมตัวเติมคำสั่งหรือไม่ API ที่ได้รับความนิยมสูงสุดที่มีอยู่ใน PHP, PDO และ MySQLi เกี่ยวข้อง ไม่ได้รับอนุญาตตัวยึดตำแหน่ง เช่นเดียวกับ API คำสั่งที่เตรียมไว้ส่วนใหญ่ในภาษาอื่น:

    // ตัวอย่าง PDO พร้อมพารามิเตอร์ที่มีชื่อ, $query ที่ไม่มีเครื่องหมายคำพูด = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (:id, :col1, :col2, :date)" ; // ตัวอย่าง MySQLi ด้วย ? พารามิเตอร์ที่ไม่มีเครื่องหมายคำพูด $query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) ค่า (?, ?, ?, ?)";

    สัญลักษณ์ที่ส่งคืนลิงก์ย้อนกลับในตัวระบุ:

    ตัวอย่างเช่น:

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

    ลองดูคำตอบนี้เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับหมุดย้อนกลับ

    ตอนนี้เกี่ยวกับเครื่องหมายคำพูดคู่และเครื่องหมายคำพูดเดี่ยว (ไมเคิลพูดถึงเรื่องนี้แล้ว)

    แต่ในการกำหนดค่า คุณต้องใช้เครื่องหมายคำพูดเดี่ยวหรือคู่ ลองดูอีกตัวอย่างหนึ่ง

    แทรกลงใน `tablename` (`id, `title`) ค่า (NULL, title1);

    ที่นี่ฉันจงใจลืมใส่ title1 ในเครื่องหมายคำพูด ตอนนี้เซิร์ฟเวอร์จะยอมรับ title1 เป็นชื่อคอลัมน์ (เช่น ตัวระบุ) ดังนั้น เพื่อระบุว่านี่คือค่า คุณต้องใช้เครื่องหมายคำพูดคู่หรือเดี่ยว

    แทรกลงใน `tablename` (`id, `title`) ค่า (NULL, "title1");

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

    $query = "INSERT INTO `table` (`id`, `col1`, `col2`) ค่า (NULL, "$val1", "$val2"");

    ตอนนี้ เมื่อใช้เครื่องหมายคำพูดคู่ใน PHP คุณจะทำให้ตัวแปร $val1 และ $val2 ใช้ค่าของมัน จึงเป็นการสร้างแบบสอบถามที่ถูกต้อง ชอบ

    $val1 = "ค่าของฉัน 1"; $val2 = "ค่าของฉัน 2"; $query = "INSERT INTO `table` (`id`, `col1`, `col2`) ค่า (NULL, "$val1", "$val2"");

    แทรกลงใน `table` (`id`, `col1`, `col2`) ค่า (NULL, "ค่าของฉัน 1", "ค่าของฉัน 2")

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

    1. BACKTICKS (`) ใช้กับชื่อตัวระบุ
    2. SINGLE QUOTES (") ใช้กับค่าต่างๆ

    และอย่างที่ @MichaelBerkowski กล่าว

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

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

    123E10 เป็นชื่อตัวระบุที่ถูกต้อง แต่ยังเป็นตัวอักษร INTEGER ที่ถูกต้องด้วย

    [โดยไม่ต้องลงรายละเอียดว่าคุณจะได้ชื่อ ID แบบนั้นได้อย่างไร] สมมติว่าฉันต้องการสร้างตารางชั่วคราวชื่อ 123456e6

    ไม่มีข้อผิดพลาดใน backticks

    DB > สร้างตารางชั่วคราว `123456e6` (`id` char (8)); แบบสอบถามตกลง 0 แถวได้รับผลกระทบ (0.03 วินาที)

    ข้อผิดพลาดถ้าคุณไม่ใช้การโทรกลับ

    DB > สร้างตารางชั่วคราว 123451e6 (`id` char (8)); ข้อผิดพลาด 1064 (42000): คุณมีข้อผิดพลาดในไวยากรณ์ SQL ของคุณ ตรวจสอบคู่มือที่สอดคล้องกับเวอร์ชันเซิร์ฟเวอร์ MariaDB ของคุณเพื่อหาไวยากรณ์ที่ถูกต้องเพื่อใช้ใกล้กับ "123451e6 (`id` char (8))" ที่บรรทัด 1

    อย่างไรก็ตาม 123451a6 เป็นชื่อ ID ที่ดี (ไม่มี backticks)

    DB > สร้างตารางชั่วคราว 123451a6 (`id` char (8)); แบบสอบถามตกลง 0 แถวได้รับผลกระทบ (0.03 วินาที)

    ทั้งหมดเป็นเพราะ 1234156e6 ก็เป็นเลขยกกำลังเช่นกัน

    ควรใช้เครื่องหมายคำพูดเดี่ยวสำหรับค่าสตริง เช่น ในรายการ VALUES()

    โดยทั่วไปแล้ว Backticks ใช้เพื่อระบุตัวระบุและอาจปลอดภัยด้วยเนื่องจากมีการใช้คีย์เวิร์ดที่สงวนไว้เป็นครั้งคราว

    เมื่อรวมกับ PHP และ MySQL เครื่องหมายคำพูดคู่และเครื่องหมายคำพูดเดี่ยวช่วยลดความยุ่งยากในการเขียนคิวรีอย่างมาก

    ราคาใน MySQL มีสองประเภท:

    1. " เพื่อรวมตัวอักษรสตริง
    2. ` เพื่อรวมตัวระบุ เช่น ชื่อตารางและคอลัมน์

    แล้วมี “อันนี้เป็นกรณีพิเศษ ใช้ได้สำหรับ. หนึ่งของเป้าหมายข้างต้นในแต่ละครั้งขึ้นอยู่กับ sql_mode ของเซิร์ฟเวอร์:

    1. ค่าเริ่มต้น"อักขระ" สามารถใช้เพื่อซ้อนตัวอักษรสตริงได้ "
    2. ในโหมด ANSI_QUOTES " สัญลักษณ์สามารถใช้เพื่อรวมตัวระบุ ANSI_QUOTES

    แบบสอบถามต่อไปนี้จะให้ผลลัพธ์ที่แตกต่างกัน (หรือข้อผิดพลาด) ขึ้นอยู่กับโหมด SQL:

    เลือก "คอลัมน์" จากตารางโดยที่ foo = "bar"

    ANSI_QUOTES ปิดการใช้งาน

    แบบสอบถามจะเลือกสตริงตัวอักษร "คอลัมน์" โดยที่คอลัมน์ foo เท่ากับสตริง "bar"

    เปิดใช้งาน ANSI_QUOTES

    แบบสอบถามจะเลือกคอลัมน์คอลัมน์โดยที่คอลัมน์ foo เท่ากับคอลัมน์

    เมื่อจะใช้

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

    มีความแตกต่างที่ชัดเจนระหว่างการใช้ " " และ " "

    เมื่อใช้ " " ตลอด จะไม่มี "การเปลี่ยนแปลงหรือการแปล" ก็พิมพ์เหมือนเดิม

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

    สิ่งที่ฉันหมายถึงโดยการแปล/การแปลงคือ: สิ่งใดก็ตามที่อยู่ในเครื่องหมายคำพูดเดียวจะไม่ถูก "แปล" เป็นค่าของมัน พวกเขาจะได้รับการยอมรับเนื่องจากอยู่ในเครื่องหมายคำพูด ตัวอย่าง: a=23 จากนั้น echo "$a" จะสร้าง $a ในเอาต์พุตมาตรฐาน ในขณะที่ echo "$a" จะสร้าง 23 ในเอาต์พุตมาตรฐาน



    2024 wisemotors.ru. วิธีนี้ทำงานอย่างไร. เหล็ก. การทำเหมืองแร่ สกุลเงินดิจิทัล