web-dev-qa-db-ja.com

準備されたステートメントと変数バインドを使用するOrderBy in Java with JDBC driver

使っています

  1. mySQLDBへのJDBC接続を確立するためのjdbcTemplate
  2. sQLインジェクション攻撃から可能な限り身を守るためのプリペアドステートメント
  3. ダースの異なる列のいずれかでデータを並べ替えるユーザーからの要求を受け入れる必要がある
  4. 次のステートメント

    jdbcTemplate.query("SELECT * FROM TABLE1 ORDER BY ? ?", colName, sortOrder);
    

もちろん、これは機能しません。変数バインディングは、クエリ内の式のパラメータ値だけで列名を指定することを想定していないためです。

それで...人々はこの問題をどのように解決していますか? Javaコードで並べ替えを行うだけで簡単な解決策のように見えますが、列を並べ替えるための変数文字列と、並べ替え順序を示す変数を取得しているためです。これは、カバーするコンパレータ条件の醜い数です。これは、それを解決するための一般的なパターンの一般的な問題であるはずです...

20
Raevik

プレースホルダー?はパラメーター値にのみ使用でき、列およびソート順の方向には使用できません。したがって、これを行うための標準的な方法は、たとえば hereString#format() またはそれに類似したものを使用して、クエリに列名と順序値を追加します。

もう1つのオプションは、Spring Data JPAを使用することです。この場合、メソッドにタイプ Sort のインスタンスを指定できます。これには、データベースをソートするために必要なすべての情報を含めることができます。

19

列名と順序をSQLクエリに連結するだけですが、

  1. 列名と順序がこのコンテキストで有効であることを確認します。
  2. SQLインジェクション 攻撃の試みに対抗するためにそれらをサニタイズします。

これは、結果をアプリケーション層にフェッチしてここで並べ替えるよりも効率的だと思います。

2
Vikdor

私の提案は、キーと列のマッピングです。それは安全ソリューションです。

最初に、可能な限り簡単な方法でマップを開始します。便宜上、get(Obiect key)メソッドをオーバーロードして、失敗した場合にdefault列( "fullName")を返すようにしました。これにより、SqlExeptionから保護されます。

    static Map<String,String> sortCol;
{
    sortCol = new HashMap<String, String>(){
        {//Enter all data for mapping
            put("name","fullName");
            put("rok","year");
            put("rate","likes");
            put("count-rate","countRate");

        }
        /**
         * 
         * @param key for column name
         * @return column name otherwise default "fullName"
         */
        @Override
        public String get(Object key) {
            String col =super.get(key);
            return null==col?"fullName":col;
        }
    };
}

簡単な使用例を次に示します。

String sqlQuery= "Select \"fullName\",year,likes,count-rate, country ..."+
 "from  blaBla..."+
 "where blaBla..."+
 "order by "+sortCol.get("keySort") "\n"; // keySort can have the value name, count-rate etc .. 

ちなみに、RESTやSOAPなど...攻撃者にとって、これは大きな助け。

0
Adam111p