データベースを SQL インジェクションから保護しようとしています。定義済みのデータ型の SETOF を返す多くのストアド関数があります。例えば:
create type userLoginUserIdPasswordReturnType as
(
userId integer, -- user.id
password text
);
CREATE OR REPLACE FUNCTION "user_login_get_id_password"(usernameIn text)
returns setof userLoginUserIdPasswordReturnType as
$$
declare
sql text;
begin
sql = 'select id, cryptpwd from "user" where username = ' || usernameIn ||';';
return query execute sql;
end;
$$ language 'plpgsql';
これらのストアド プロシージャを Java フロントエンドから呼び出したいと思います。私が読んだことから、SQL インジェクションに関しては CallableStatement を使用する方が安全です。これは私がこれまでに持っているものです:
public ArrayList<String> userLoginGetIdPassword(String username){
ArrayList<String> result = new ArrayList<String>();
try{
String commandText = "{call user_login_get_id_password(?)}";
this.cstmt = this.myConnection.prepareCall(commandText);
this.cstmt.setObject(1, username);
// this.rs = this.cstmt.execute();
this.rs = cstmt.executeQuery();
while (this.rs.next()){
result.add(this.rs.getString(1));
}
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
return result;
}
execute() メソッドを使用しようとすると、ResultSet rs をブール値に設定するように求められます。そのまま実行すると (executeQuery())、returnType の最初のフィールド (userId) のみが ResultSet に表示されます。
ストアドプロシージャをそのまま呼び出す場合:
public ArrayList<String> userLoginGetIdPassword(String username){
ArrayList<String> result = new ArrayList<String>();
try{
String query = "select \"user_login_get_id_password\"('" + username + "');";
System.out.println(query);
this.stmt = this.myConnection.createStatement();
this.rs = this.stmt.executeQuery(query);
while (this.rs.next()){
result.add(this.rs.getString(1));
}
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
return result;
}
正しいデータを取得します。
また、データベースを SQL インジェクションから保護するためのヒントが他にある場合は、親切に指摘してください。アプリケーションが使用する特定の Postgres ロールを作成し、データベースに接続するための ConnectionPool (c3p0) を実装しました。アプリケーションはローカル ネットワークで実行されます。SQL インジェクション攻撃 (コメント --、セミコロン、*、および DELETE などの他の SQL コマンド) を回避するために、さまざまな Java Swing コンポーネントからのユーザー入力を検証しています。
どんな入力でも大歓迎です。
ありがとう。