У меня есть код jOOQ 3.14.4, Scala 2.13, смешанный с устаревшим Play
кодом:
val user = Option(sql
.selectFrom(USER)
.where(USER.EMAIL.equal(email))
.and(USER.PASSWORD.equal(crypto.sign(password)))
.fetchOne())
Обратите внимание, что email
и password
— это String
s.
Теперь я хочу заменить код, который использует устаревший метод Play
, новым методом Java (который я получил из библиотеки Crypto
):
public static boolean checkpw(String plaintext, String hashed)
1. Как я могу использовать jBCrypt
внутри кода jOOQ?
BCrypt.checkpw(...)
не возвращает логическое значение, и как мне извлечь фактическое строковое значение в USER.PASSWORD equal
?
Пример использования метода TableField
:
// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
System.out.println("It matches");
else
System.out.println("It does not match");
2. Является ли BCrypt.checkpw
безопасным с криптографической точки зрения для целей шифрования паролей для их сохранения в производственной базе данных?
Я не знаю ответа на ваш второй вопрос (который я рекомендую вам задать в новом вопросе. Эти два вопроса не связаны). Вот ответ на ваш первый:
- Как я могу использовать BCrypt.checkpw(...) внутри кода jOOQ?
С этой сигнатурой метода вам придется извлекать хешированный пароль из вашей базы данных, а не проверять его с помощью SQL. Вы не можете выполнить логику Java, стоящую за checkpw
в базе данных. Вместо этого сделайте следующее:
val user = Option(sql
.selectFrom(USER)
.where(USER.EMAIL.equal(email))
.fetchOne())
.filter(u => BCrypt.checkpw(password, u.getPassword))
@rapt: я очень полагаюсь на предположение, что электронное письмо уникально среди пользователей, потому что вы тоже делаете это в своем запросе, и я не могу представить себе систему и никогда не видел ее, где имело бы смысл обратное, хотя, мне любопытно, чтобы меня поправили.
Вы правы, электронная почта уникальна среди пользователей. Что здесь полезно. — Я имел в виду, что в других случаях, когда есть необходимость сделать fetch
, прежде чем использовать какой-либо алгоритм фильтрации на записях, извлеченных из базы данных, может оказаться, что извлекается много записей, а не одна. Хорошо, что здесь такого не было.
Потрясающий! Похоже, это то, что я могу сделать, если мне придется использовать
BCrypt.checkpw
. Он думает, что вы полагаетесь на предположение, чтоemail
используется одним пользователем, иначе он может вернуть более одной записи, и производительность может быть плохой. Я также посмотрел, что на самом деле делаетcheckpw
, и он действительно вызывает хеш-методBCrypt.hashpw
, но делает больше, чем просто проверяет, еслиhashpw(password, salt) == saved_password
(мне не ясно, почему). Если я просто сделаю сравнение сохранённых и вновь посчитанных хэшей, то с jooq у меня получится.and(USER.PASSWORD.equal(BCrypt.hashpw(password, BCrypt.gensalt())))