2017-02-03 10 views
0

ユーザーがレコードのランダム化された%を選択できるようにします。おそらく10%または20%、またはその間のどこかのように。私は準備文を使ってみました:選択したパーセンテージのPreparedステートメント

Connection con = null; 
PreparedStatement stmt = null; 
ResultSet rs = null; 

try { 
    con = cpds.getConnection(); 
    stmt = con.prepareStatement("SELECT TOP ? PERCENT Table.Name, FROM Table" 
      " WHERE Table.Color = ?"+ 
    stmt.setString(1, percentVal); 
    stmt.setString(2, colorVal); 
} catch (SQLException e) { 
    e.printStackTrace(); 
}finally{ 
    try {con.close();} catch (SQLException e1) {} 
    try {rs.close();} catch (SQLException e1) {} 
    try {stmt.close();} catch (SQLException e1) {} 
} 

しかし、私はnullpointerexceptionを取得します。

私が知っているに動作しますが

Connection con = null; 
PreparedStatement stmt = null; 
ResultSet rs = null; 

try { 
    con = cpds.getConnection(); 
    stmt = con.prepareStatement("SELECT TOP "+percentVal+" PERCENT Table.Name, FROM Table" 
      " WHERE Table.Color = ?"+ 
    stmt.setString(1, colorVal); 
} catch (SQLException e) { 
    e.printStackTrace(); 
}finally{ 
    try {con.close();} catch (SQLException e1) {} 
    try {rs.close();} catch (SQLException e1) {} 
    try {stmt.close();} catch (SQLException e1) {} 
} 

あるしかし、私は、これは、SQLインジェクションの脆弱性であると思いますか?これを行うには良い方法がありますか?

答えて

0

コンパイル済みのサーバー側のプリペアドステートメントは、効率が良く、オーバーヘッドが少なく、インジェクションができないように設計されています。 しかし、SELECT句のプレースホルダを処理するようには設計されていない可能性があります。たとえば、MySQLはここに有効なプレースホルダの場所に関するいくつかの詳細を指定します:https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html

特定のDBとドライバの仕様をチェックして、有効であることを確認します。

これ以外にも、範囲外の値(SELECT TOP 200 PERCENTなど)や数値以外の値(SELECT TOP ABC PERCENTなど)によって発生したSQLエラーを回避するために、ユーザー入力の検証が行われます。それを考えると、データのパーセンテージを整理して、その点からステートメントを準備することができます。

+0

"SELECT TOP" + percentVal + "PERCENT ..."と書くのはまったくありません。ステートメントに貼り付ける前にpercentValを検証すると、うまくいくはずです。 – arsarc

+0

ユーザーの入力を直接スティックする必要はありません。 Integer.parseIntを検証の一部として使用し、代わりに使用することができます。これは、注入の試みではなく数値であることを保証することができます。 Double.parseDoubleまたはFloat.parseFloatは入力に適しています。 – sjgp

関連する問題