Пока было время добавил шифрование паролей в один проект. Программист, который начинал его делать, почему-то не озаботился этим с самого начала.В результате все пароли хранились в открытом виде, что недопустимо. Пароли нужно всегда шифровать специальными алгоритмами вроде bcrypt, не стоит пользоваться алгоритмами, которые изначально для этого не предназначались, вроде MD5 или SHA.
Сначала нам нужно объявить бин bcryptEncoder класса org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder в spring-security.xml нашего проекта:
1 2 |
<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> |
Затем в секции authentication-provider добавить строчку <password-encoder ref="bcryptEncoder"/> вот так:
1 2 3 4 5 |
<authentication-manager> <authentication-provider user-service-ref="userService"> <password-encoder ref="bcryptEncoder"/> </authentication-provider> </authentication-manager> |
Если вы используете свою реализацию authentication-provider, то вам нужно будет вручную сравнивать пароль с помощью метода bcryptEncoder.matches(rawPassword, encryptedPassword) , что может выглядеть примерно так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; // ... other imports public final class DatabaseAuthenticationProvider implements AuthenticationProvider { private static final Logger logger = LoggerFactory .getLogger(DatabaseAuthenticationProvider.class); private UserDetailsService userDetailsService; private BCryptPasswordEncoder bcryptEncoder; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { logger.info("authenticate started."); String password = authentication.getCredentials().toString(); String userName = authentication.getName(); UserDetails userDetails = userDetailsService .loadUserByUsername(userName); User user = ((UserDetailsImpl) userDetails).getUser(); if (user == null) { logger.error("User not found. UserName=" + userName); throw new BadCredentialsException(userName); } else if (!user.getActivated()) { logger.error("Not activated."); throw new NotActivatedException(userName); } else if (!user.getEnabled()) { logger.error("Not enabled."); throw new DisabledException(userName); } else { if (bcryptEncoder.matches(password, user.getPassword())) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); logger.info("authenticate finished."); return token; } else { logger.error("Password does not match. UserName=" + userName); throw new BadCredentialsException(userName); } } } @Override public boolean supports(Class<? extends Object> authentication) { return UsernamePasswordAuthenticationToken.class .isAssignableFrom(authentication); } public void setUserService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } public void setBcryptEncoder(BCryptPasswordEncoder bcryptEncoder) { this.bcryptEncoder = bcryptEncoder; } } |
В тех местах кода, где вы задаёте новый пароль пользователю, нужно зашифровать новый пароль перед сохранением в базу данных с помощью метода bcryptEncoder.encode(newPassword).
Спасибо огромное! То что надо, коротко и ясно.
Неплохо, но к сожалению, это хеширование, а не шифрование.
Шифрование подразумевает двустороннее преобразование (шифрование/дешифрование)
К сожалению, да. Тут я, видимо, с терминологией напутал.
по крайней мере со стандартным диалогом авторизации, дешафирование не нужно, spring сам всё сделает и проверит на равенство