【问题标题】:Validating credentials using JDBC against PostgreSQL使用 JDBC 针对 PostgreSQL 验证凭据
【发布时间】:2021-09-27 16:40:51
【问题描述】:

所以我一直在尝试让我的凭据在我登录到我的服务器时得到验证。 这是我要验证的一组简单数据。

(456789, 'Dave123', '密码', 'Dave', 'Davidson', 'dave@dadavid', 2), (123456, 'John456', '123456', '约翰', '约翰逊', 'john@jojohn', 1), (456878, 'Kate789', 'abcdef', 'Kate', 'Kateson', 'kate@kitkat', 1)

public class LoginService {
//username and password with id identifier
    //0 for false, 1 for employee and 2 for manager
    public boolean login(String username, String password, int id) {
        
        
        
try(Connection connection = ConnectionUtil.getConnection()) {
            
            ResultSet resultSet = null; // intialize an empty resultset that will store the results of our query.
            //sql statement to get all of the info from reimbursement
            String sql = "select * from users where username =? and pass=? and user_role_id=?"
                    + "values (?,?,?)";
            
            
            PreparedStatement preparedStatement = connection.prepareStatement(sql); 
            
            preparedStatement.setString(2, username );
            preparedStatement.setString(3, password );
            preparedStatement.setInt(7, id);
            
            if(username.equals(username) && password.equals(password) && id == (1) ) {
                return true;
            }
            if(username.equals(username) && password.equals(password) && id == (2) ) {
                return true;
            }
        
        }catch (Exception e) {
        // TODO: handle exception
    }
return false;
    }
}

所以当它完成验证时,如果用户名和密码在数据库中,它将返回 true。否则,它会返回一个假,并且不让用户登录。但是目前它所做的只是返回假,并且不让用户登录。

我尝试在邮递员上运行它,它会接受这些值并让我登录,但在实时服务器上尝试它会拒绝它。

 <input id="username" type="text" placeholder="username" class="col-sm-4 form-control">
 <input id="password" type="password" placeholder="password" class="col-sm-4 form-control"> 
 <input id="id" type="number" placeholder ="id" class="col-sm-4 formcontrol">

这就是我的 html 中的内容。

【问题讨论】:

  • 您的preparedStatement.setXxx() 调用似乎遗漏了几个参数。我假设您忽略了这些调用,但如果没有,您很可能会遇到异常,因为查询的参数不完整。此外,//TODO: handle exception 是您应该首先 修复的东西,因为现在您正在吞下它,因此您不会得到任何信息。如果您现在不能以其他方式处理它,至少打印堆栈跟踪。顺便说一句,捕获特定异常以进行更具体的处理,而不仅仅是记录。
  • 您的代码的其他问题:1)您甚至没有执行准备好的语句,因此它可以做任何事情。 2)username.equals(username) &amp;&amp; password.equals(password) 基本上将参数与它们自己进行比较,这总是正确的(除非一个为空并且你得到一个 NPE)。 3)不要比较代码中的凭据,而是使用查询 anc 检查它是否返回某些内容。 4)为了更好的安全性,看看密码散列和加盐,或者最好使用像 Keycloak 这样的身份提供者。

标签: java sql postgresql


【解决方案1】:

您的 SQL 查询一开始就是错误的。但更重要的是,您甚至没有运行该查询,也没有处理查询的结果。

select 语句的 values 子句无效。所以删除它。

String sql = "select * from users where username =? and pass=? and user_role_id=?";

你只有三个参数,所以你需要用数字 1,2 和 3(不是 2,3,7)传递它们

preparedStatement.setString(1, username );
preparedStatement.setString(2, password );
preparedStatement.setInt(3, id);

那么您必须使用execute() 来实际运行查询并接收结果:

ResultSet rs = preparedStatement.execute();

在您调用next() 之后,返回的值随后从ResultSet 而非语句中检索,例如:

if (rs.next()) {
  String nameFromDb = rs.getString("username");
  String pwdFromDb = rs.getString("password");
  int id = rs.getInt("id");
}

但是由于所有三个参数都是 WHERE 子句的一部分,因此您永远不会得到值与输入不同的结果。所以你只需要检查查询是否返回了一行:

if (rs.next()) {
  return true;
}

您需要在返回之前关闭preparedStatement(),以避免数据库中的资源泄漏。

【讨论】:

    猜你喜欢
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 2018-09-09
    • 2013-02-15
    • 1970-01-01
    • 2020-11-20
    相关资源
    最近更新 更多