Две позиции шифрования паролей в Spring Boot!

Spring Boot
Две позиции шифрования паролей в Spring Boot!

Давайте поговорим об этом: пароль не может быть расшифрован. Не спрашивайте, как расшифровать пароль в проекте микролюдей брата Сун!

Пароль не может быть расшифрован или для обеспечения безопасности системы. Сегодня Brother Song расскажет вам о том, как обращаться с паролями, чтобы обеспечить максимальную безопасность нашей системы.

Эта статья является 20-й в серии Spring Security. Чтение предыдущих статей этой серии поможет вам лучше понять эту статью:

  1. Выкопайте большую яму и позвольте Spring Security сделать это!
  2. Song Ge поможет вам начать работу с Spring Security, не спрашивайте, как снова расшифровать пароль.
  3. Научите, как настроить вход в форму в Spring Security
  4. Spring Security разделяет внешний и внутренний интерфейсы, давайте не будем переходить по страницам! Все взаимодействия JSON
  5. Операции авторизации в Spring Security оказались такими простыми
  6. Как Spring Security хранит пользовательские данные в базе данных?
  7. Spring Security+Spring Data Jpa объединяют усилия, управление безопасностью становится еще проще!
  8. Spring Boot + Spring Security реализует функцию автоматического входа в систему
  9. Spring Boot автоматически входит в систему, как контролировать риски безопасности?
  10. В проекте микросервиса, где Spring Security лучше, чем Shiro?
  11. Два способа для Spring Security настроить логику аутентификации (расширенный игровой процесс)
  12. Как быстро просмотреть IP-адрес пользователя для входа в систему и другую информацию в Spring Security?
  13. Spring Security автоматически удаляет предыдущего пользователя, вошедшего в систему, одна конфигурация выполнена!
  14. Spring Boot + Vue разделяет интерфейсные и серверные проекты, как выгнать вошедших в систему пользователей?
  15. Spring Security поставляется с собственным брандмауэром! Вы даже не представляете, насколько безопасна ваша система!
  16. Что такое атака с фиксацией сеанса? Как защититься от атак фиксации сеанса в Spring Boot?
  17. Развертывание кластера, как Spring Security обрабатывает совместное использование сеансов?
  18. Song Ge учит вас, как защищаться от CSRF-атак в SpringBoot! так легко!
  19. Учиться учиться досконально! Анализ исходного кода защиты от CSRF в Spring Security

1. Зачем шифровать

21 декабря 2011 года кто-то опубликовал в Интернете базу данных, содержащую 6 миллионов пользовательских данных CSDN, которые хранятся в виде обычного текста, включая имена пользователей, пароли и зарегистрированные адреса электронной почты. После инцидента CSDN опубликовала заявление на Weibo, официальном сайте и других каналах, пояснив, что эта база данных использовалась для резервного копирования в 2009 году, а ее утечка произошла по неизвестным причинам. В течение следующих десяти дней к этому инциденту были причастны многие компании, такие как Kingsoft, NetEase, JD.com, Dangdang и Sina. Самое шокирующее во всем инциденте то, что CSDN хранит пароли пользователей в виде простого текста, а поскольку многие пользователи используют один и тот же пароль для нескольких веб-сайтов, утечка пароля веб-сайта вызовет большие риски для безопасности. Из-за большого количества уроков, извлеченных из прошлого, когда мы строим систему сейчас, пароль должен быть зашифрован.

Эта утечка тоже оставила кое-что интересное, особенно для большинства программистов по установке паролей. Люди нашли несколько интересных паролей из утекших файлов CSDN, например:

  • ppnn13%dkstFeb.1stКитайский анализ этого пароля таков: Пингпинг завивает более тринадцати, кончик кардамона в начале февраля.
  • csbt34.ydhl12sКитайский анализ этого пароля таков: три или четыре часа на пруду и один или два звука иволги внизу листа.
  • ...

И так далее и тому подобное, вы обнаружите, что многие программисты обладают очень высокими гуманистическими качествами, что поразительно.

2. Схема шифрования

Как правило, мы будем использовать функцию шифрования паролей HASH, также известную как алгоритм хэширования, хэш-функция, которая является способом создания цифрового «отпечатков пальцев» из любых данных.

Хэш-функция сжимает сообщение или данные в дайджест, уменьшает объем данных, исправляет формат данных, а затем шифрует и смешивает данные для воссоздания хэш-значения. Хэш-значение обычно представляется короткой строкой случайных букв и цифр. Хорошие хэш-функции редко имеют хеш-коллизии во входной области. В хеш-таблицах и обработке данных отсутствие подавления коллизий для различения данных может затруднить поиск записей в базе данных.

Нашими часто используемыми хэш-функциями являются алгоритм дайджеста сообщения MD5 и алгоритм безопасного хеширования.

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

Для повышения безопасности пароля, как правило, необходимо добавить соль во время процесса шифрования пароля.Так называемая соль может быть случайным числом или именем пользователя.После добавления соли пароли, сгенерированные пользователями с один и тот же пароль открытого текста не совпадает. , что может значительно повысить безопасность пароля.

Традиционный метод добавления соли требует специального поля в базе данных для записи значения соли.Это может быть поле имени пользователя (поскольку имя пользователя уникально) или поле, предназначенное для записи значения соли. конфигурация громоздкая.

Spring Security предоставляет множество схем шифрования паролей. Официальная рекомендация — использовать BCryptPasswordEncoder. BCryptPasswordEncoder использует надежную хеш-функцию BCrypt. Разработчики могут выбрать защиту и экземпляры SecureRandom при их использовании. Чем больше сила, тем больше итераций ключа, а число итераций ключа равно 2^силе. Значение прочности находится в диапазоне от 4 до 31, а значение по умолчанию равно 10.

В отличие от Shiro, который необходимо справиться с паролями и солями, в весенней безопасности BCRYPPASSWORDECODER поставляется со своей собственной солью, которая очень удобна для обработки.

3. Практика

3.1 кодек шифрования

commons-codec — это проект с открытым исходным кодом на Apache, который может легко реализовать шифрование паролей. Сун Гэ вV 部落Эта схема принята в проекте (GitHub.com/Len VE/v блог…Spring Security еще не представила время BCryptPasswordEncoder, commons-codec — относительно распространенное решение.

Итак, здесь я сначала расскажу об использовании commons-codec.

Сначала нам нужно ввести зависимости commons-codec:

<dependency>
	<groupId>commons-codec</groupId>
	<artifactId>commons-codec</artifactId>
	<version>1.11</version>
</dependency>

Затем настройте PasswordEncoder:

@Component
public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return encodedPassword.equals(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()));
    }
}

В Spring Security PasswordEncoder специально используется для обработки шифрования и сравнения паролей.Мы настраиваем MyPasswordEncoder и реализуем интерфейс PasswordEncoder.Нам также необходимо реализовать два метода в этом интерфейсе:

  1. Метод encode означает шифрование пароля. Параметр rawPassword — это пароль в виде открытого текста, который вы передали, а возвращаемый зашифрованный текст — это зашифрованный зашифрованный текст. Схема шифрования здесь использует MD5.
  2. Метод match предназначен для сравнения паролей, параметр rawPassword эквивалентен паролю, переданному при входе пользователя в систему, а encodedPassword эквивалентен зашифрованному паролю (запрошенному из базы данных).

Наконец, не забудьте отметить MyPassWordenCoder в качестве компонента в весеннем контейнере через аннотацию @Component.

Таким образом, когда пользователь входит в систему, будет автоматически вызываться метод match для сравнения паролей.

Конечно, после использования MyPasswordEncoder, когда пользователь регистрируется, пароль должен быть зашифрован и сохранен в базе данных следующим образом:

public int reg(User user) {
    ...
    //插入用户,插入之前先对密码进行加密
    user.setPassword(passwordEncoder.encode(user.getPassword()));
    result = userMapper.reg(user);
    ...
}

На самом деле это очень просто, достаточно вызвать метод encode для шифрования пароля. Для получения полного кода вы можете обратиться к племени V (GitHub.com/Len VE/v блог…

3.2 Шифрование BCryptPasswordEncoder

Но определить PasswordEncoder самостоятельно все еще немного проблематично, особенно при работе с солью паролей.

Он обеспечивает BCRyptPassWordencoder в весенней безопасности, так что зашифрованный пароль очень легко легко. Bean BcryptpasswordeCoder нужно только предоставить этот экземпляр, Micro персонал является использованием этой программы (GitHub.com/Len VE/v HR),…

@Bean
PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(10);
}

Параметр 10, переданный при создании BCryptPasswordEncoder, — это сила, то есть количество итераций ключа (или не настроено, по умолчанию — 10). При этом пароль сконфигурированного пользователя памяти уже не 123, а следующим образом:

auth.inMemoryAuthentication()
.withUser("admin")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
.roles("ADMIN", "USER")
.and()
.withUser("sang")
.password("$2a$10$eUHbAOMq4bpxTvOVz33LIehLe3fu6NwqC9tdOcxJXEhyZ4simqXTC")
.roles("USER");

Пароль здесь — это пароль, зашифрованный с помощью BCryptPasswordEncoder.Хотя зашифрованные пароли admin и sang разные, открытый текст — 123. После завершения настройки используйте admin/123 или sang/123 для входа в систему.

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

@Service
public class RegService {
    public int reg(String username, String password) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10);
        String encodePasswod = encoder.encode(password);
        return saveToDb(username, encodePasswod);
    }
}

После того как пользователь передаст пароль из внешнего интерфейса, пароль шифруется путем вызова метода encode в экземпляре BCryptPasswordEncoder, а зашифрованный текст сохраняется в базе данных после завершения шифрования.

4. Анализ исходного кода

Наконец, давайте посмотрим немного PasswordEncoder.

PasswordenCoder - это интерфейс с только тремя методами:

public interface PasswordEncoder {
	String encode(CharSequence rawPassword);
	boolean matches(CharSequence rawPassword, String encodedPassword);
	default boolean upgradeEncoding(String encodedPassword) {
		return false;
	}
}
  • Метод encode используется для шифрования пароля.
  • Метод match используется для сравнения паролей.
  • upgradeEncoding указывает, нужно ли снова шифровать пароль, чтобы сделать его более безопасным. Значение по умолчанию — false.

Spring Security предоставляет множество реализаций для PasswordEncoder:

Но, если честно, со времен BCryptPasswordEncoder мы мало внимания уделяли другим классам реализации.

Метод кодирования в PasstementenCod вызывается вручную, когда мы регистрируемся в регистрации пользователя.

Метод match вызывается системой, по умолчанию он вызывается в методе DaoAuthenticationProvider#additionalAuthenticationChecks.

protected void additionalAuthenticationChecks(UserDetails userDetails,
		UsernamePasswordAuthenticationToken authentication)
		throws AuthenticationException {
	if (authentication.getCredentials() == null) {
		logger.debug("Authentication failed: no credentials provided");
		throw new BadCredentialsException(messages.getMessage(
				"AbstractUserDetailsAuthenticationProvider.badCredentials",
				"Bad credentials"));
	}
	String presentedPassword = authentication.getCredentials().toString();
	if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
		logger.debug("Authentication failed: password does not match stored value");
		throw new BadCredentialsException(messages.getMessage(
				"AbstractUserDetailsAuthenticationProvider.badCredentials",
				"Bad credentials"));
	}
}

Как видите, сравнение паролей выполняется с помощью метода passwordEncoder.matches.

Для вызывающего процесса DaoAuthenticationProvider вы можете обратиться кДва способа для Spring Security настроить логику аутентификации (расширенный игровой процесс)одна статья.

Что ж, сегодня я кратко расскажу о шифровании Spring Security с моими друзьями.