ホームページ  >  記事  >  プリコンパイルによって SQL インジェクションが妨げられる理由

プリコンパイルによって SQL インジェクションが妨げられる理由

(*-*)浩
(*-*)浩オリジナル
2019-05-10 17:33:1612620ブラウズ

プリコンパイルによって SQL インジェクションが防止される理由は、データベースがパラメーター化されたクエリを実行できるようになるためです。パラメータ化されたクエリを使用する場合、データベースはパラメータの内容を SQL 実行の一部としてではなく、フィールドの属性値としてみなします。このようにして、パラメータに破壊的なステートメント (または '1=1' ) が含まれている場合でも、実行されません。

プリコンパイルによって SQL インジェクションが妨げられる理由

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。