Написание пользовательской области tomcat с использованием bcrypt

Я работаю над веб-приложением на основе Java, используя Tomcat 7.0 в качестве сервера приложений. После полезных ответов на предыдущий вопрос , Я решил использовать bcrypt для безопасного хранения паролей в моей HSQLDB. Однако реализации Realm по умолчанию в Tomcat не могут обрабатывать bcrypt, поэтому мне нужно написать свой собственный; это единственная причина, по которой я пишу настраиваемую область, хотя, как и во всех других случаях, простой JDBCRealm будет работать. Я искал в Google и смотрел примеры, и я немного запутался в нескольких моментах.

Во-первых, следует ли расширять RealmBase или JDBCRealm? Большинство примеров, которые я нашел, используют RealmBase, но я успешно использовал JDBCRealm для приложения до этого момента (поскольку он все еще находится в разработке, я начал с хранения паролей в виде открытого текста и просто использовал JDBCRealm для обработки аутентификации) и один ответ на вопрос о Code Ranch рекомендовал просто расширить это. Однако я не совсем уверен, какие методы мне нужно переопределить в этом случае. Просто метод аутентификации или что-то еще? Если бы это было так, JDBCRealm по-прежнему мог бы обрабатывать и управлять ролями пользователей, getPrincipal и всем остальным?

Во-вторых, в приведенном выше примере CodeRanch, если я чего-то не упускаю, кажется, что метод getPassword возвращает незашифрованный пароль. Поскольку я собираюсь использовать bcrypt, это невозможно, и я думаю, что это в любом случае кажется нецелесообразным. В других примерах, например в этом сообщении в блоге, getPassword, кажется, просто возвращает пароль прямо из базы данных. Итак, какой путь правильный? Я не могу найти, для чего именно используется getPassword; в документации не сказано. Можно ли для этого просто вернуть зашифрованное значение, хранящееся в базе данных?

Если кто-нибудь может сказать мне, какой класс мне следует расширить, какие методы следует переопределить и что должно возвращать getPassword, я был бы очень признателен.


person Maltiriel    schedule 05.09.2012    source источник


Ответы (1)


После некоторых проб и ошибок я понял, как это сделать. Я расширил JDBCRealm и переопределил только метод аутентификации, и он отлично работает. Я поместил BCrypt.java в тот же каталог, что и моя настраиваемая область, и этот код сработал. :

import java.security.Principal;
import org.apache.catalina.realm.JDBCRealm;
public class BCryptRealm extends JDBCRealm
{
  @Override
  public Principal authenticate(String username, String credentials)
  {
    String hashedPassword = getPassword(username);
    // Added this check after discovering checkpw generates a null pointer
    // error if the hashedPassword is null, which happens when the user doesn't
    // exist. I'm assuming returning null immediately would be bad practice as
    // it would let an attacker know which users do and don't exist, so I added
    // a call to hashpw. No idea if that completely solves the problem, so if
    // your application has more stringent security needs this should be
    // investigated further.
    if (hashedPassword == null)
    {
      BCrypt.hashpw("fakePassword", BCrypt.gensalt());
      return null;
    }
    if (BCrypt.checkpw(credentials, hashedPassword))
    {
      return getPrincipal(username);
    }
    return null;
  }
}

person Maltiriel    schedule 10.09.2012
comment
Откуда вы взяли реализацию Bcrypt? - person Jonathan S. Fisher; 04.08.2013
comment
Я продолжаю получать ошибки, я не знаю почему. Я использовал приведенный выше код, и теперь Tomcat вызывает этот метод для аутентификации. - person C_B; 17.07.2014