A word of warning: passwords are undecipherable. We also do not ask songko micro personnel project password how to decrypt!

The password cannot be decrypted, again to ensure system security. Today, Songo is here to talk to you about how to handle passwords in order to ensure the maximum security of our system.

This is the 20th article in the Spring Security series, and reading previous articles in this series will help you understand it better:

  1. Dig a big hole and Spring Security will do it!
  2. How to decrypt the password
  3. A step-by-step guide to customizing form logins in Spring Security
  4. Spring Security does front and back separation, so don’t do page jumps! All JSON interactions
  5. Authorization in Spring Security used to be so simple
  6. How does Spring Security store user data into the database?
  7. Spring Security+Spring Data Jpa, Security management is only easier!
  8. Spring Boot + Spring Security enables automatic login
  9. Spring Boot automatic login. How to control security risks?
  10. How is Spring Security better than Shiro in microservices projects?
  11. Two ways for SpringSecurity to customize authentication logic (advanced play)
  12. How can I quickly view information such as the IP address of the login user in Spring Security?
  13. Spring Security automatically kicks out the previous login user.
  14. How can I kick out a user who has logged in to Spring Boot + Vue?
  15. Spring Security comes with a firewall! You have no idea how secure your system is!
  16. What is a session fixed attack? How do I defend against session fixation attacks in Spring Boot?
  17. How does Spring Security handle session sharing in a clustered deployment?
  18. Songgo hand in hand to teach you in SpringBoot CSRF attack! So easy!
  19. Learn to learn thoroughly! Spring Security CSRF defense source code parsing

1. Why encrypt

On December 21, 2011, a database containing 6 million CSDN user data was published on the network. The data were all stored in plain text, including user names, passwords and registered email addresses. After the incident, CSDN issued a statement on weibo, its official website and other channels, explaining that the database was used for backup in 2009 and had been leaked for unknown reasons. It had reported to the police, and then issued a public apology letter on its official website. In the following ten days, kingsoft, netease, JINGdong, Dangdang, Sina and other companies were involved in the incident. The most shocking thing in the whole event is that CSDN stores user passwords in plain text. Since many users share the same password with multiple websites, the disclosure of one website’s password will cause great security risks. Because of all this, when we build systems now, we encrypt our passwords.

The leak also leaves some interesting questions, especially about setting passwords for programmers. Some of the amusing passwords found in the CSDN leak include the following:

  • ppnn13%dkstFeb.1stAtop the mountains atop the cardamom atop the pilgrims in early February.
  • csbt34.ydhl12sGreen moss on the pond three or four, oriole at the bottom of the leaf one or two
  • .

And so on and so on, you will find that many programmers humanistic literacy is still very high, let a person TSK TSK.

2. Encryption scheme

Password encryption We usually use hash functions, also known as hash algorithms, hash functions, which are a method of creating a digital “fingerprint” from any data.

A hash function compresses a message or data into a summary, reduces the size of the data, fixes the format of the data, and then scrambles and remixes the data to create a hash. A hash value is usually represented by a short random string of letters and numbers. Good hash functions have fewer hash collisions in the input field. In hash tables and data processing, not suppressing conflicts to differentiate data can make database records harder to find.

Common Hash functions include MD5 message digest Algorithm and Secure Hash Algorithm.

However, using the hash function alone is not enough. If the passwords of two users have the same plaintext, the ciphertext generated will also be the same, which increases the risk of password leakage.

To enhance password security, salt is usually added during password encryption. The salt can be a random number or a user name. After salt is added, the ciphertext generated by users with the same password in plain text is different, which greatly improves password security.

The traditional method of adding salt requires a special field in the database to record the salt value. This field may be a user name field (because the user name is unique) or a special field to record the salt value, which is cumbersome to configure.

BCryptPasswordEncoder is recommended. BCryptPasswordEncoder is recommended to use the BCrypt strong hash function. The developer has the option of providing strength and SecureRandom instances at the time of use. The greater the strength, the more iterations of the key, which is 2^strength. The value of strength ranges from 4 to 31. The default value is 10.

Unlike Shiro, which requires you to salt your own password, BCryptPasswordEncoder has its own salt in Spring Security, making it very easy to process.

Practice 3.

3.1 the codec encryption

Commons – Codec is an open source project on Apache that makes it easy to encrypt passwords. This is what Songo is doing with the V Tribe project (github.com/lenve/VBlog… Back when Spring Security didn’t offer BCryptPasswordEncoder, Commons-Codec was a relatively common solution.

So I’m going to introduce you to the use of Commons -codec.

First we need to introduce the commons-codec dependency:

<dependency>
	<groupId>commons-codec</groupId>
	<artifactId>commons-codec</artifactId>
	<version>1.11</version>
</dependency>
Copy the code

Then customize a 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) {
        returnencodedPassword.equals(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes())); }}Copy the code

In Spring Security, PasswordEncoder is used to encrypt and compare passwords. We define MyPasswordEncoder and implement PasswordEncoder interface. We also need to implement two methods in this interface:

  1. Encode method means to encrypt the password, the parameter rawPassword is the plaintext password you pass, the return is the encrypted ciphertext, the encryption scheme used MD5.
  2. The matches method matches passwords. The rawPassword parameter matches the password passed in when the user logs in, and the encodedPassword matches the encrypted password (queried from the database).

Finally, remember to mark the MyPasswordEncoder as a Component in the Spring container via the @Component annotation.

When a user logs in, the matches method is automatically called for password matching.

Of course, after using MyPasswordEncoder, the password needs to be encrypted and stored in the database when the user registers, in the following way:

public int reg(User user) {...// Insert the user. Encrypt the password before inserting the useruser.setPassword(passwordEncoder.encode(user.getPassword())); result = userMapper.reg(user); . }Copy the code

In fact, very simple, is to call the encode method to encrypt the password. The complete code can be found in the V tribe (github.com/lenve/VBlog…

3.2 BCryptPasswordEncoder encryption

But defining the PasswordEncoder yourself is a bit tricky, especially when dealing with password salting.

So BCryptPasswordEncoder is provided in Spring Security to make password encryption and salting very easy. Simply provide an instance of the BCryptPasswordEncoder Bean, which is used by micro personnel (github.com/lenve/vhr)…

@Bean
PasswordEncoder passwordEncoder(a) {
    return new BCryptPasswordEncoder(10);
}
Copy the code

When creating the BCryptPasswordEncoder, the parameter 10 passed in is strength, which is the number of iterations of the key (optionally, 10 is the default). At the same time, the password of the memory user is not 123, as follows:

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

The password here is the encrypted password using BCryptPasswordEncoder. Although the encrypted passwords of admin and Sang are different, the plaintext is 123. After the configuration, use admin/123 or sang/123 to log in.

This example uses a user configured in memory. Generally, the user information is stored in the database, so the password needs to be encrypted during user registration, as follows:

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

After the user sends the password from the front end, it encrypts the password by calling the encode method in the BCryptPasswordEncoder instance. After the encryption, the ciphertext is stored in the database.

4. Source code analysis

Finally, let’s take a look at the PasswordEncoder a little bit.

PasswordEncoder is an interface that contains only three methods:

public interface PasswordEncoder {
	String encode(CharSequence rawPassword);
	boolean matches(CharSequence rawPassword, String encodedPassword);
	default boolean upgradeEncoding(String encodedPassword) {
		return false; }}Copy the code
  • The encode method is used to encrypt passwords.
  • The matches method is used to match passwords.
  • UpgradeEncoding Indicates whether the password needs to be encrypted again to make it more secure. The default value is false.

Spring Security provides a number of implementations for PasswordEncoder:

But to be honest, since BCryptPasswordEncoder, we’ve paid very little attention to other implementation classes.

The encode method in PasswordEncoder is called manually when the user registers.

Matches method, it is the system call, default is in DaoAuthenticationProvider# additionalAuthenticationChecks method call.

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")); }}Copy the code

As you can see, password matching is done using the passwordEncoder. Matches method.

Process of DaoAuthenticationProvider calls, you can reference SpringSecurity custom authentication logic (advanced game) is in one of two ways.

Today, I will talk about Spring Security encryption with my friends. If you have any gains, remember to point to songge under the encouragement of watching