flawopen.com/SQL Injection di Java/MyBatis
MyBatis ${} vs #{}: mencegah SQL Injection
Bayangkan #{value} sebagai slot terlindungi pada prepared statement: database memperlakukannya sebagai data. ${value} menyalin teks ke SQL sebelum disiapkan.
Nilai terikat vs teks SQL mentah
<select id="getUser">
SELECT * FROM users
WHERE id = ${id}
</select>
// Raw substitution: the SQL text changes
<select id="getUser">
SELECT * FROM users
WHERE id = #{id}
</select>
// MyBatis creates a PreparedStatement parameter
Mengapa MyBatis menyediakan kedua sintaks
#{} mengikat nilai sebagai parameter JDBC PreparedStatement. Parameter tidak mewakili sintaks SQL seperti nama tabel, kolom, atau arah urutan. ${} mengganti teks langsung tanpa escape. Utamakan statement statis atau cabang <choose>. Jika perlu, pilih identifier utuh dari allowlist server; jangan interpolasikan teks permintaan sembarang.
Saat identifier dinamis diperlukan
Parameter terikat tidak menggantikan identifier. Petakan pilihan urutan ke fragmen SQL tetap di server (atau gunakan <choose>). Jangan kirim kolom, tabel, atau ASC/DESC dari klien langsung ke ${}. Escape atau kutip tidak mengamankan SQL sembarang.
Cara mengaudit mapper MyBatis
rg -n -F '${' --glob '*.xml' --glob '*.java' .Pertanyaan umum
Ya. Aturannya sama. ${column} di @Select menyisipkan teks mentah; ikat nilai dengan #{value} dan allowlist identifier.
Tidak. Tinjau hasil; SQL mungkin dirakit di tempat lain. Tambahkan pemeriksaan XML dan anotasi serta uji agar pilihan urutan hanya memakai fragmen tetap yang diharapkan.