Function 返回“myType”集合的JDBC Postgres存储函数调用

Function 返回“myType”集合的JDBC Postgres存储函数调用,function,postgresql,jdbc,callable,Function,Postgresql,Jdbc,Callable,我试图保护我的数据库不受SQL注入的影响。我有许多存储函数返回一组预定义的数据类型。例如: create type userLoginUserIdPasswordReturnType as ( userId integer, -- user.id password text ); CREATE OR REPLACE FUNCTION "user_login_get_id_password"(usernameIn text) returns setof userLoginUserIdP

我试图保护我的数据库不受SQL注入的影响。我有许多存储函数返回一组预定义的数据类型。例如:

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前端调用这些存储过程。据我所知,使用CallableStatement比SQL注入更安全。这就是我迄今为止所做的:

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设置为boolean。如果按executeQuery的方式运行,则在结果集中只能看到returnType的第一个字段userId

如果我这样调用存储过程:

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来连接到我的数据库——应用程序将在本地网络上运行。我正在验证来自不同JavaSwing组件的用户输入,以避免SQL注入攻击comment、、分号、*和其他SQL命令,如DELETE

欢迎任何意见


谢谢。

首先,PostgreSQL不支持call命令,这就是第一种方法失败的原因

在第二种方法中,您将遇到两个问题。第一个是SQL注入。使用标准绑定方法可以解决这个问题。您的第二个问题是,您将很难从您调用的函数中解析回数据

更好的方法是

SELECT * FROM user_login_get_id_password(?)
但是请注意,sql注入在函数内部是可能的。在一定程度上,你可以避免执行保护你的命令。如果必须使用execute,请将查询字符串更改为:

sql =  'select id, cryptpwd from "user" where username = ' || quote_literal(usernameIn);
执行查询中不需要终止分号。它会自动终止。如果引用表/列名,您确实需要调用quote_literal,尽管使用quote_ident