1. Обзор
В Spring Security 4 можно было хранить пароли в виде обычного текста, используя аутентификацию в памяти.
Капитальный пересмотр процесса управления паролями в версии 5 ввел более безопасный механизм по умолчанию для кодирования и декодирования паролей. Это означает, что если ваше приложение Spring хранит пароли в виде обычного текста, обновление до Spring Security 5 может вызвать проблемы.
В этом коротком уроке мы опишем одну из этих потенциальных проблем и продемонстрируем решение.
2. Пружинная безопасность 4
Мы начнем с показа стандартной конфигурации безопасности, которая обеспечивает простую аутентификацию в памяти (действительна для Spring 4):
@Configuration public class InMemoryAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring") .password("secret") .roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/private/**") .authenticated() .antMatchers("/public/**") .permitAll() .and() .httpBasic(); } }
Эта конфигурация определяет аутентификацию для всех /частных/ сопоставленных методов и открытый доступ для всего, что находится в разделе /public/.
Если мы используем ту же конфигурацию в Spring Security 5, мы получим следующую ошибку:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
Ошибка говорит нам о том, что данный пароль не может быть декодирован, так как кодировщик паролей не был настроен для нашей аутентификации в памяти .
3. Пружинная безопасность 5
Мы можем исправить эту ошибку, определив Делегирование PasswordEncoder с помощью класса PasswordEncoder Factories .
Мы используем этот кодер для настройки нашего пользователя с помощью AuthenticationManagerBuilder:
@Configuration public class InMemoryAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); auth.inMemoryAuthentication() .withUser("spring") .password(encoder.encode("secret")) .roles("USER"); } }
Теперь, с этой конфигурацией, мы храним наш пароль в памяти с помощью BCrypt в следующем формате:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
Хотя мы можем определить свой собственный набор кодеров паролей, рекомендуется придерживаться кодеров по умолчанию , предоставленных в PasswordEncoderFactories .
3.2. NoOpPasswordEncoder
Если по какой-либо причине мы не хотим кодировать настроенный пароль, мы можем использовать NoOpPasswordEncoder .
Для этого мы просто префиксим парольную фразу, которую мы предоставляем методу password () , идентификатором {noop} :
@Configuration public class InMemoryNoOpAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring") .password("{noop}secret") .roles("USER"); } }
Таким образом, Spring Security будет использовать NoOpPasswordEncoder под капотом, когда он сравнивает пароль, предоставленный пользователем, с тем, который мы настроили выше.
Обратите внимание, однако, что мы никогда не должны использовать этот подход в производственном приложении! Как говорится в официальной документации, NoOpPasswordEncoder устарел , чтобы указать, что это устаревшая реализация, и ее использование считается небезопасным .
3.3. Перенос Существующих Паролей
Мы можем обновить существующие пароли до рекомендуемых стандартов Spring Security 5,:
- Обновление сохраненных паролей в виде обычного текста с кодированием их значений:
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);
- Префиксация хэшированных сохраненных паролей с их известным идентификатором кодера:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS {sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
- Запрос пользователей на обновление их паролей, когда механизм кодирования сохраненных паролей неизвестен
4. Заключение
В этом кратком примере мы обновили допустимую конфигурацию проверки подлинности Spring 4 в памяти до Spring 5, используя новый механизм хранения паролей.
Как всегда, вы можете найти исходный код в проекте GitHub .