ในบทความก่อนหน้านี้ฉันแนะนำความแตกต่างระหว่างพารามิเตอร์ # {} และ $ {} และความแตกต่างระหว่าง # และ $ ใน mybatis หากคุณต้องการคุณสามารถอ้างอิงได้
$ และ # คำอธิบายง่าย ๆ :
# เทียบเท่ากับการเพิ่มคำพูดสองเท่าให้กับข้อมูลและ $ เทียบเท่ากับการแสดงข้อมูลโดยตรง
1. สรุป
เมื่อใช้ SQLMAP สำหรับการสืบค้น SQL ใน myBatis มักจะจำเป็นต้องส่งพารามิเตอร์แบบไดนามิก Dynamic SQL เป็นหนึ่งในคุณสมบัติที่ทรงพลังของ mybatis และเป็นเหตุผลสำคัญว่าทำไมมันถึงเหนือกว่ากรอบ ORM อื่น ๆ ก่อนที่จะทำการคอมไพล์คำสั่ง SQL MyBatis จะแยกวิเคราะห์ SQL แบบไดนามิกและแยกวิเคราะห์ลงในวัตถุ BoundSQL ซึ่งถูกประมวลผลที่นี่ด้วย ในขั้นตอนการแยกวิเคราะห์ SQL แบบไดนามิก #{} และ $ {} จะมีการแสดงที่แตกต่างกันและ #{} จะถูกแยกวิเคราะห์ลงในเครื่องหมายพารามิเตอร์สำหรับคำสั่ง JDBC precompiled
A #{} แยกวิเคราะห์เป็นตัวยึดพารามิเตอร์หรือไม่? - $ {} เป็นเพียงการเปลี่ยนสตริงบริสุทธิ์และการเปลี่ยนตัวแปรจะดำเนินการในระหว่างขั้นตอนการแยกวิเคราะห์ SQL แบบไดนามิก
2. คำอธิบายข้อผิดพลาด
พารามิเตอร์ส่วนหน้า:
ข้าม: 0
รับ: 10
RULENAME: A, B, C
การประมวลผลเลเยอร์ธุรกิจ:
แพ็คเกจ SQL;/*** Escape Parameters Multi-Select แบบเลือกส่วนหน้าเป็นเนื้อหาคำสั่ง SQL*/คลาสสาธารณะ SQLUTIL {Private Final String String replaceChar_Comma = ","; String String สุดท้ายส่วนตัว "ABC"; System.out.println ("Comma-Separated:" + FormatInsTr (S1)); System.out.println ("แยกพื้นที่:" + formatInstr (S2));} private String String String String String (String Querystr) == querystr || "" .Equals (querystr.trim ())) return null; querystr = querystr.replaceall (sqlutil.replacechar_comma, ""). replaceall (replacechar_semicolon, " {ถ้า (null == querystrs || 0 == querystrs.length) return null; stringbuffer buf = new Stringbuffer (); สำหรับ (int i = 0; i <querystrs.length; i ++) {ถ้า (i! = 0) buf.append (","); buf.toString ();}} การประมวลผลเลเยอร์ Mapper:
// การจัดการข้อผิดพลาด <ถ้า test = "rulename! = null และ rulename! = ''"> และ a.rule_name ใน (#{rulename}) </if> // การจัดการที่ถูกต้อง <ถ้า test = "rulename! = null และ rulename! = '' ' บันทึกคำอธิบาย:
[DEBUG] [2016-08-02 17: 42: 42.226] [QTP1457334982-157] Java.SQL.Connection-==> การเตรียม: เลือก A.ID, A.IS_VALID, A.Rule_lable, A.Rule_name A.GMT_MODIFIED, A. การสั่งซื้อจาก idc_logistics_assign_rules ตัวเข้าร่วมซ้าย app_user c บน c.work_no = a.modifier และ c.is_deleted = 'n', idc_sp_info b โดยที่ ASIS_DELETED = 'N' จำกัด ?,? [DEBUG] [2016-08-02 17: 42: 42.226] [QTP1457334982-157] Java.SQL.PreparedStatement-==> พารามิเตอร์: 'A', 'B' (String), 0 (จำนวนเต็ม), 10 (Integer)
การวิเคราะห์ผลลัพธ์: เลเยอร์ Mapper มี SQL ที่คอมไพล์ไว้ล่วงหน้าและมีตัวยึดตำแหน่งสำหรับ #? แต่มันจะถูกแทนที่โดยตรงสำหรับ $
PS: เมื่อใช้คำสั่งซื้อโดยพารามิเตอร์แบบไดนามิกเมื่อเรียงลำดับ mybatis คุณต้องใส่ใจกับการใช้ $ แทน #
เปลี่ยนสตริง
โดยค่าเริ่มต้นการใช้ไวยากรณ์รูปแบบ #{} ทำให้ MyBatis สร้างคุณสมบัติคำสั่งที่ประมวลผลล่วงหน้าและตั้งค่าความปลอดภัยด้วยเป็นพื้นหลัง (เช่น?) สิ่งนี้ปลอดภัยและรวดเร็วและบางครั้งคุณก็ต้องการแทรกสตริงที่ไม่เปลี่ยนเป็นคำสั่ง SQL โดยตรง ตัวอย่างเช่นการสั่งซื้อโดยคุณสามารถใช้เช่นนี้:
การคัดลอกรหัสมีดังนี้:
สั่งซื้อโดย $ {columnName}
ที่นี่ mybatis จะไม่แก้ไขหรือหลบหนีสตริง
สำคัญ: ไม่ปลอดภัยที่จะรับเอาต์พุตเนื้อหาจากผู้ใช้และมอบให้กับสตริงที่ไม่เปลี่ยนแปลงในคำสั่ง สิ่งนี้สามารถนำไปสู่การโจมตีการฉีด SQL ที่มีศักยภาพดังนั้นคุณไม่ควรอนุญาตให้ผู้ใช้เข้าสู่ฟิลด์เหล่านี้หรือมักจะหลบหนีและตรวจสอบด้วยตัวเอง