GlassFish SHA-256 дайджест-аутентификация
Я хранил свои пароли в виде простого текста для целей разработки, но хочу вместо этого начать хранить хэши, но пока еще не удалось должным образом обеспечить GlassFish аутентификацию по хеш-паролю из-за следующей исключительной ситуации SecurityException:
SEVERE: jdbcrealm.invaliduserreason
WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
Во-первых, я использую GlassFish 3.1 и настроил дайджест для моей области JDBC на SHA-256.
мой User
класс имеет следующее поле аннотированного пароля:
@Basic(fetch = FetchType.LAZY)
@Column(length = 45, nullable = false)
private String password;
Следующий хелпер-метод отвечает за хеширование пароля:
private byte[] digest(String input) {
byte[] output = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
output = md.digest(input.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
}
return output;
}
Затем я устанавливаю пароль для пользователя следующим образом:
u.setPassword(Base64.encode(digest(password)).toString());
Я бы не кодировал Base64, потому что это кажется недокументированным, но этот вопрос: Glassfish Security - jdbcRealm: Как настроить вход в систему с дайджестом SHA-256, говорит о том, что вам нужно это сделать.
Поэтому я предполагаю, что мне хотелось бы знать, ожидает ли GlassFish String (VARCHAR) или byte[] (BLOB) в качестве поля пароля в базе данных, правильно ли я хэширую пароль, и правильно ли он дополнительно кодировать Base64 хэш пароля?
Спасибо!
1 ответ
Ожидает ли GlassFish строку (VARCHAR) или байт [] (BLOB) в качестве поля пароля в базе данных?
Ожидается столбец, который отображается на тип Java java.lang.String
в JDBC, и это, как правило, CHAR, VARCHAR и т. д. LOB не будут работать, так как реализация области JDBC выдает ResultSet.getString
вызов метода для получения хэша пароля.
Правильно ли я хэширую пароль и правильно ли дополнительно Base64 кодировать хэш пароля?
Кодировка Base64 - не единственная поддерживаемая опция. Вы также можете выполнять шестнадцатеричное кодирование. Но вы должны выполнить любой из них и настроить JDBC Realm для выполнения того же во время выполнения. При отсутствии параметра кодирования Glassfish преобразует последовательность байтов, связанную с дайджестом, в последовательность символов в charset
настроен для области.
Я подозреваю, что проблема связана с упоминанием кодировки UTF-8 в выражении input.getBytes("UTF-8")
, Стоит проверить, соответствует ли кодировка Base64 результата, предоставленного вашим digest
Метод фактически совпадает с хешами паролей, хранящимися в базе данных.
Кроме того, учитывая причину jdbcrealm.invaliduserreason
Я также подозреваю, что может быть выполнено одно из следующих условий:
- Параметр кодирования не указан для области JDBC; предпочтительно должен быть один из
base64
или жеhex
(случай не имеет значения, исходя из исходного кода области JDBC), в противном случае вы окажетесь в сценарии, в котором массив байтов дайджеста преобразуется в массив символов (который, на мой взгляд, немного ненадежен, если вы не можете гарантировать что пароль, предоставленный пользователями, всегда находится в определенной кодировке). - Для пользователя в базе данных не существует хэша пароля. Смотрите мой предыдущий ответ по выполненному SQL-запросу; Возможно, вы захотите выполнить запрос самостоятельно. Вы можете регистрировать заявления, выпущенные Derby (если вы используете их в качестве базы данных), поместив файл с именем
derby.properties
в расположении вашей базы данных Derby со свойствомderby.language.logStatementText=true
в этом. При закрытии базы данных файл derby.log будет заполнен всеми запросами, выполненными сервером приложений. - Оператор SQL, подготовленный Glassfish, неверен.
- Соединение с базой данных не может быть установлено.