プリコンパイルによって SQL インジェクションが防止される理由は、データベースがパラメーター化されたクエリを実行できるようになるためです。パラメータ化されたクエリを使用する場合、データベースはパラメータの内容を SQL 実行の一部としてではなく、フィールドの属性値としてみなします。このようにして、パラメータに破壊的なステートメント (または '1=1' ) が含まれている場合でも、実行されません。
PreparedStatement で SQL インジェクションをある程度防ぐことができるのはなぜですか?
PreparedStatement は SQL をプリコンパイルします。データベースは SQL を初めて実行する前に分析、コンパイル、最適化されます。同時に、実行計画もキャッシュされるため、データベースは次のことを行うことができます。パラメータ化されたクエリを作成します。パラメータ化されたクエリを使用する場合、データベースはパラメータの内容を SQL 実行の一部としてではなく、フィールドの属性値としてみなします。このようにして、パラメータに破壊的なステートメント (または '1=1' ) が含まれている場合でも、実行されません。
推奨コース: Java チュートリアル
PreparedStatement の使い方SQL インジェクション攻撃を回避するにはどうすればよいですか? PreparedStatement と Statement の違いとその利点は何ですか?
PreparedStatement の簡単な例
public class JDBCTest { public static void main(String[] args) { //表示使用Unicode字符集;字符编码设置为utf-8;不使用SSL连接 String URL = "jdbc:mysql://127.0.0.1:3306/sampledb?useUnicode=true&" + "characterEncoding=utf-8&useSSL=false"; String USER = "spring4";//用户 String PASSWORD = "spring4";//密码 Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { //1.加载驱动程序到JVM Class.forName("com.mysql.jdbc.Driver"); //2.创建数据库连接 conn = DriverManager.getConnection(URL, USER, PASSWORD); //3.创建Statement,实现增删改查 String sql = "select user_id,user_name,credits from t_user where credits > ?"; st = conn.prepareStatement(sql);//这里使用PreparedStatement st.setInt(1, 8); //4.向数据库发送SQL命令 rs = st.executeQuery(); //5.使用ResultSet处理数据库的返回结果 while (rs.next()) { System.out.println(rs.getLong("user_id") + " " + rs.getString("user_name") + " " + rs.getString("credits")); } } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { //6.关闭资源 try { rs.close(); st.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
Statement のいくつかの実装
Statement オブジェクトは、SQL ステートメントをデータベースに送信するために使用されます。
Statement が SQL ステートメントを実行するたびに、データベースは SQL ステートメントのコンパイルを実行する必要があります。クエリが 1 回だけ実行され、結果が返される状況で使用するのが最適です。
1. 静的 SQL ステートメントを実行します。通常、Statement インスタンスを通じて実装されます。
2. 動的 SQL ステートメントを実行します。通常は PreparedStatement インスタンスを通じて実装されます。
3. データベース ストアド プロシージャを実行します。通常は CallableStatement インスタンスを通じて実装されます。
'#' と '$'
SQL プリコンパイルの違いは、SQL ステートメントとパラメーターをサーバーに送信する前に、データベース ドライバーが SQL ステートメントをコンパイルすることを指します。 DBMS: この方法では、DBMS が SQL を実行するときに、再コンパイルする必要がありません。
‘#{ }’: JDBC 準備済みステートメント (準備済みステートメント) のパラメーター マーカーとして解析され、‘ #{ }’ はパラメーター プレースホルダー ? として解析されます。
‘${ }’ は単なる文字列の置換であり、変数の置換は動的 SQL 解析フェーズ中に実行されます。プリコンパイル前にすでに変数に置換されています
'${ }' 変数の置換フェーズは動的 SQL 解析フェーズにあり、'#{ }' 変数の置換は DBMS で行われます。
PreparedStatement と Statement の違いは何ですか
1.PreparedStatement はプリコンパイルでき、このプリコンパイルされた SQL クエリ ステートメントは将来のクエリで再利用できます。 Statement オブジェクトよりも高速にクエリを生成します。
2.PreparedStatement は動的にパラメータ化されたクエリを作成できます
3.PreparedStatement は SQL インジェクション攻撃を防ぐことができます
4.PreparedStatement クエリは読みやすく、条件を追加できます ステートメントは複雑です
5.PreparedStatement では、プレースホルダー (?) に複数の値を含めることはできません
以上がプリコンパイルによって SQL インジェクションが妨げられる理由の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。