Использование JDBCRealm для аутентификации пользователя с помощью Shiro

Я пытаюсь выполнить аутентификацию сервлета, работающего в Tomcat 6, используя Shiro.

У меня есть следующий файл siro.ini:

[main]
ps = org.apache.shiro.authc.credential.DefaultPasswordService
pm = org.apache.shiro.authc.credential.PasswordMatcher
pm.passwordService = $ps

aa = org.apache.shiro.authc.credential.AllowAllCredentialsMatcher
sm = org.apache.shiro.authc.credential.SimpleCredentialsMatcher

jof = org.apache.shiro.jndi.JndiObjectFactory
jof.resourceName = jdbc/UserDB
jof.requiredType = javax.sql.DataSource
jof.resourceRef = true

realm = org.apache.shiro.realm.jdbc.JdbcRealm
realm.permissionsLookupEnabled = true
realm.credentialsMatcher = $pm
; Note factories are automatically invoked via getInstance(),
;   see org.apache.shiro.authc.config.ReflectionBuilder::resolveReference
realm.dataSource = $jof

securityManager.realms = $realm

[urls]
/rest/** = authcBasic
/prot/** = authcBasic

И в моей базе данных следующее:

mysql> select * from users;
+----------+------------------+----------+----------------------------------------------+--------------------------+
| username | email            | verified | password                                     | password_salt            |
+----------+------------------+----------+----------------------------------------------+--------------------------+
| admin    | [email protected]********* |        1 | ojSiTecNwRF0MunGRvz3DRSgP7sMF9EAR77Ol/2IAY8= | eHp9XedrIUa5sECfOb+KOA== |
+----------+------------------+----------+----------------------------------------------+--------------------------+
1 row in set (0.00 sec)

Если я использую SimpleCredentialsManager, он аутентифицирует штраф против пароля открытого текста в таблице users. Попытка использовать PasswordMatcher была крайне расстраивающей.

Пароль и пароль_salt были получены с помощью утилиты shiro-tools Hasher.

Когда я пытаюсь выполнить аутентификацию с помощью базового сервлета HelloWorld, который я использую для тестирования (path = rest/hello, context =/ws), в журналах я получаю следующее:

15:35:38.667 [http-8080-2] TRACE org.apache.shiro.util.ClassUtils - Unable to load clazz named [ojSiTecNwRF0MunGRvz3DRSgP7sMF9EAR77Ol/2IAY8=] from class loader [WebappClassLoader
  context: /ws
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
[email protected]
]

(Полный журнал https://gist.github.com/recurse/5915693)

Кажется, что пытается загрузить мой хешированный пароль как имя класса. Является ли это ошибкой или ошибкой конфигурации с моей стороны? Если это ошибка, как я могу ее обойти? Если это ошибка конфигурации, что мне не хватает?

Ответ 1

Во-первых, спасибо за предоставление большого количества информации по этому вопросу - это облегчает предоставление ответа.

Посмотрев на список строк в строке примера, не отображается, что вы сохраняете вывод, который ожидает PasswordService при выполнении сравнения хэшированных паролей. Например:

$ java -jar ~/.m2/repository/org/apache/shiro/tools/shiro-tools-hasher/1.2.2/shiro-tools-hasher-1.2.2-cli.jar -p
Password to hash:
Password to hash (confirm):
$shiro1$SHA-256$500000$uxaA2ngfdxdXpvSWzpuFdg==$hOJZc+3+bFYYRgVn5wkbQL+m/FseeqDtoM5mOiwAR3E=

Строка, начинающаяся с $shiro1$, будет сохранена в столбце password в базе данных. Нет необходимости в отдельном столбце соли, поскольку вся информация, которую требуется Сиро, находится в строке $shiro1$....

DefaultPasswordService использует те же параметры конфигурации по умолчанию (SHA-256, 500 000 итераций и т.д.), поэтому, если вы используете инструмент Хашера CLI, как я показал выше (нет дополнительной конфигурации алгоритма хеширования), вам не нужно для дальнейшей настройки DefaultPasswordService POJO. Однако, если вы измените параметры хэширования в CLI, вам необходимо убедиться, что те же параметры настроены на DefaultPasswordService bean (и/или его внутреннем HashingService).

Если вы все еще тестируете и можете изменить свою схему БД, я бы рекомендовал сделать это сейчас, чтобы иметь одно поле пароля, в котором хранится строка $shiro1$.... Затем вы используете PasswordService, как описано здесь в разделе Использование:

http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/credential/PasswordService.html