【问题标题】:Converting VARBINARY values into String in a Select Query in MySQL?在 MySQL 的选择查询中将 VARBINARY 值转换为字符串?
【发布时间】:2018-11-20 01:22:00
【问题描述】:

根据这个answer,我应该将我的String BCrypt哈希密码passHash保存为BINARYBINARY(60)(我选择BINARY(60))我的 MySQL 表(我将它存储在名为 passHash 的列中)。

现在,当我从表中选择 passHash 列值并将其检索到 Java 中时,它现在是 byte[] 数据类型。

然后我如何将它转换回它的 String 形式,以便我可以使用下面的validateLogin() 方法对其进行验证:

//Validate username and password login
    public boolean validateLogin(String username, String userpass) 
    {
        boolean status = false;  
        PreparedStatement pst = null; 
        ResultSet rs = null;  

        User user = new User(); //This is my Java bean class

        try(Connection connect= DBConnection.getConnection())
        {
            //Here, passHash is stored as VARBINARY(60) 
            pst = connect.prepareStatement("SELECT * FROM user WHERE username=? and passHash=?;"); 

            pst.setString(1, username);  
            pst.setString(2, userpass);  
            //Here's where I'm having difficulty because `passHash` column in my user table is VARBINARY(60) while `userpass` is a String

            rs = pst.executeQuery(); 
            status = rs.next();  
        } 

        catch (SQLException e) 
        {
            e.printStackTrace();
        }
            return status;  //status will return `true` if `username` and `userpass` matches what's in the columns
    }

usernameuserpass 参数用于获取用户在我的Login.jsp 表单中的输入:

String username = request.getParameter("username");
String userpass = request.getParameter("userpass");

编辑:我的BCrypt代码如下:

//returns a hashed String value
public static String bCrypt (String passPlain) {
        return BCrypt.hashpw(passPlain, BCrypt.gensalt(10));
    }

//Returns a true if plain password is a match with hashed password
public static Boolean isMatch(String passPlain, String passHash){
        return (BCrypt.checkpw(passPlain, passHash));
    }

【问题讨论】:

标签: java mysql jsp login password-hash


【解决方案1】:

当您创建用户帐户时,您必须以某种方式对密码进行散列处理以在 Java 中生成 byte[],然后将其插入到您的 user 表中。

public static byte[] bCrypt (String passPlain) {
    return BCrypt.hashpw(passPlain, BCrypt.gensalt(10)).getBytes();
}

// here is how you generate the hash
byte[] hashed = bCrypt(userpass).toBytes();

// here is how you authenticate a login
String password; // from the UI
String sql = "SELECT passHash FROM user WHERE username = ?";
pst = connect.prepareStatement(sql);
pst.setString(1, username);
rs = pst.executeQuery();

if (rs.next()) {
    byte[] hash = rs.getBytes(1);
    if (isMatch(password, new String(hash))) {
        // authenticate
    }
}

检查现有密码的模式是传入纯文本密码和哈希。

【讨论】:

  • 我的哈希函数返回一个哈希字符串值而不是一个字节[](如我上面的编辑中所述)。当我在 MySQL 表的passHash 列中保存并插入此字符串值时,我使用了setString(myHashedStringPassword)
  • @JamesMcTyre 我的回答没有太大变化。目前尚不清楚为什么当您的表存储 byte[] 时,您的散列函数会返回 String
  • 您好,感谢您的帮助。但是,如果我尝试将bCrypt() 重构为返回byte(),我将不得不向后做更多的工作,因为hashpw() 应该返回String。有什么办法可以将原始返回的String 转换为byte[] 用于我的bCrypt()
  • 是的,我已经告诉过你了,使用String#getBytes()。但是,如果您的模式需要二进制输入,那么为什么不让您的代码保持一致呢?我的意思是,除了将哈希密码字符串粘贴到您的用户表中之外,您还在做什么?
  • 我查明了问题所在:pst.setBytes(2, hashed)(或pst.setString(2, hashedString))正在逐个字符地比较实际字符串。例如,如果我的passHash 列中存储的值是$2a$10$gnzKum16RdSXjoNk5fdv7u,那么登录仅在hashedString(或其等效的转换字节[] hashed)也完全是$2a$10$gnzKum16RdSXjoNk5fdv7u 时才有效。问题是:BCrypt 会为同一个密码生成许多不同的哈希值。所以像helloWorld 这样的密码可以生成上述哈希或不同的哈希。这就是我卡住的地方。
猜你喜欢
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多