.authoritiesByUsernameQuery(
"select username, authority from UserAuthorities " +
"where username=?")
.passwordEncoder(new StandardPasswordEncoder("53cr3t");
}
Метод passwordEncoder() принимает любую реализацию интерфейса PasswordEncoder Spring Security. Криптографический модуль Spring Security включает в себя несколько таких реализаций:
-BCryptPasswordEncoder—применяется bcrypt строгое шифрование хэширования (Applies bcrypt strong hashing encryption)
-NoOpPasswordEncoder—не применяется шифрование
-Pbkdf2PasswordEncoder—применяется PBKDF2 шифрования
-SCryptPasswordEncoder—применяется scrypt ширование хэширования (Applies scrypt hashing encryption)
-StandardPasswordEncoder—применяется SHA-256 ширование хэширования (Applies SHA-256 hashing encryption)
Предыдущий код использует StandardPasswordEncoder. Но можно выбрать любую из других реализаций или даже предоставить собственную пользовательскую реализацию, если ни одна из готовых реализаций не соответствует вашим потребностям. Интерфейс PasswordEncoder довольно прост:
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
}
Независимо от того, какой кодировщик паролей вы используете, важно понимать, что пароль в базе данных никогда не декодируется. Вместо этого пароль, который пользователь вводит при входе в систему, кодируется с использованием того же алгоритма, а затем сравнивается с закодированным паролем в базе данных. Это сравнение выполняется в Passwordencoder методе matches().
В конечном счете, вы будете хранить пользовательские данные Taco Cloud в базе данных. Однако вместо того, чтобы использовать jdbcAuthentication(), у меня есть другой вариант аутентификации. Но прежде чем мы к нему перейдем, давайте посмотрим, как можно настроить Spring Security полагаться на еще один источник данных пользователей: LDAP (облегченный протокол доступа к каталогам).
4.2.3 Хранилище пользователей в LDAP
Для настройки Spring Security для аутентификации на основе LDAP можно использовать метод ldapAuthentication(). Этот метод является LDAP аналогом jdbcAuthentication(). Следующий метод configure() показывает простую конфигурацию для аутентификации LDAP:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchFilter("(uid={0})")
.groupSearchFilter("member={0}");
}
Методы userSearchFilter() и groupSearchFilter() используются для предоставления фильтров для базовых запросов LDAP, которые используются для поиска пользователей и групп. По умолчанию базовые запросы как для пользователей, так и для групп пусты, что указывает на то, что поиск будет выполняться из корня иерархии LDAP. Но вы можете изменить это, указав базовый запрос:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.groupSearchBase("ou=groups")
.groupSearchFilter("member={0}");
}
Метод userSearchBase() предоставляет базовый запрос для поиска пользователей. Аналогичным образом, метод groupSearchBase() определяет базовый запрос для поиска групп. Вместо поиска в корневом каталоге в этом примере указывается, что пользователей следует искать в организационном разделе людей. Группы следует искать в том месте, где находится организационный раздел групп.
НАСТРОЙКА СРАВНЕНИЯ ПАРОЛЕЙ
Стратегия по умолчанию для аутентификации перед LDAP должна выполнить операцию привязки, аутентифицируя пользователя непосредственно к серверу LDAP. Другой вариант - выполнить операцию сравнения. Для этого необходимо отправить введенный пароль в каталог LDAP и попросить сервер сравнить пароль с атрибутом пароля пользователя. Потому что сравнение делается в LDAP-сервером, пароль остается в тайне.
Если вы предпочитаете аутентификацию путем сравнения паролей, вы можете реализваоть это с помощью метода passwordCompare():
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.groupSearchBase("ou=groups")
.groupSearchFilter("member={0}")
.passwordCompare();
}
По умолчанию пароль, указанный в форме входа, будет сравниваться со значением атрибута userPassword в записи LDAP пользователя. Если пароль хранится в другом атрибуте, можно указать имя атрибута пароля с помощью passwordAttribute():
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.groupSearchBase("ou=groups")
.groupSearchFilter("member={0}")
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("passcode");
}
В этом примере указывается, что атрибут passcode должен сравниваться с заданным паролем. Кроме того, вы также указываете кодировщик паролей. Приятно, что фактический пароль хранится в секрете на сервере при сравнении паролей на стороне сервера. Но попытка ввода пароля все равно передается по проводам на сервер LDAP и может быть перехвачена хакером. Чтобы предотвратить это, можно указать стратегию шифрования, вызвав метод passwordEncoder().