Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

Writing in the front

Today we continue with Spring Security. A few days ago we talked about what kind of Security framework Spring Security is and how to build a user authentication system

In my opinion, the user authentication system is divided into two parts: one is the user and the other is the authentication (as I understand it).

So this article starts with one part of it: the user object

User objects in Spring Security

The user object in Spring Security is used to describe users and manage user information, involving four core objects: UserDetails, GrantedAuthority, UserDetailsService, and UserDetailsManager.

  • UserDetails: Refers to the user in Spring Security

  • GrantedAuthority: Defines the operation rights of a user.

  • UserDetailsService: Defines the query operation for UserDetails.

  • UserDetailsManager: Extends the UserDetailsService, adding functions such as creating users and changing user passwords

It looks simple and easy to understand, keep reading!

Let’s start with the UserDetails interface, which holds the UserDetails:


public interface UserDetails extends Serializable {
 
    // Obtain permission information of the user
    Collection<? extends GrantedAuthority> getAuthorities();
 
    // Get the password
    String getPassword(a);
	 
	// Get the user name
    String getUsername(a);
 
	// Determine whether the account is invalid
    boolean isAccountNonExpired(a);
 
    // Determine whether the account has been locked
    boolean isAccountNonLocked(a);
 
    // Check whether the credential information of the account is invalid
    boolean isCredentialsNonExpired(a);
 
    // Check whether the user is available
    boolean isEnabled(a);
}
Copy the code

With UserDetails, we can obtain basic information about the user and determine its current status. At the same time, we can also see that a set of GrantedAuthority objects are saved in the UserDetails. GrantedAuthority specifies a method to obtain permission information, as shown below:

public interface GrantedAuthority extends Serializable {
    // Get permission information
    String getAuthority(a);
}
Copy the code

UserDetails also has a subinterface, MutableUserDetails. We look at the

//MutableUserDetails is an immutable interface by name
// The variable is the password
interface MutableUserDetails extends UserDetails {
    // Set the password
    void setPassword(String password);
}
Copy the code

How do I create a user object

If we wanted to create a UserDetails object in our application, we could use the chaining syntax shown below:

UserDetails user = User.withUsername("admin") 
  .password("123456") 
  .authorities("read"."write") 
  .accountExpired(false) 
  .disabled(true) 
  .build();
Copy the code

Spring Security also provides a UserBuilder object to assist in building UserDetails in a similar way:

User.UserBuilder builder = 
	User.withUsername("admin");
 
UserDetails user = builder
  .password("123456") 
  .authorities("read"."write")
  .accountExpired(false) 
  .disabled(true) 
  .build();
Copy the code

In Spring Security, a UserDetailsService is provided specifically for UserDetails. This interface is used to manage UserDetails and is defined as follows:

public interface UserDetailsService {
 
    // Get user information based on the user name
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
Copy the code

UserDetailsManager inherits UserDetailsService and provides a set of operation interfaces for UserDetails:

public interface UserDetailsManager extends UserDetailsService {
    // Create a user
    void createUser(UserDetails user);
 
    // Update the user
    void updateUser(UserDetails user);
 
    // Delete the user
    void deleteUser(String username);
 
    // Change the password
    void changePassword(String oldPassword, String newPassword);
 
    // Check whether the specified user exists
    boolean userExists(String username);
}
Copy the code

How to Store users

From the above explanation, the relationship between several core user objects is clear, next we need to further clarify the specific implementation process.

Let’s look at the two implementation classes of UserDetailsManager:

  • One is based on memory storage InMemoryUserDetailsManager,
  • One is JdbcUserDetailsManager based on relational database storage.

Here, we analyzes JdbcMemoryUserDetailsManager, for example, the createUser method is as follows:

public void createUser(final UserDetails user) {
        validateUserDetails(user);
 
        getJdbcTemplate().update(createUserSql, ps -> {
             ps.setString(1, user.getUsername());
             ps.setString(2, user.getPassword());
             ps.setBoolean(3, user.isEnabled());
 
             int paramCount = ps.getParameterMetaData().getParameterCount();
             if (paramCount > 3) {
                 ps.setBoolean(4, !user.isAccountNonLocked());
                 ps.setBoolean(5, !user.isAccountNonExpired());
                 ps.setBoolean(6,! user.isCredentialsNonExpired()); }});if(getEnableAuthorities()) { insertUserAuthorities(user); }}Copy the code

As you can see, the JdbcTemplate tool class in the Spring framework is used to insert data and store GrantedAuthority.

UserDetailsManager is a relatively independent code line, in order to complete the user information configuration, there is also another codelines, namely UserDetailsManagerConfigurer. This class maintains a list of UserDetails and provides a set of withUser methods to initialize the user information, as shown below:

private final List<UserDetails> users = new ArrayList<>();
 
public final C withUser(UserDetails userDetails) {
        this.users.add(userDetails);
        return (C) this;
}
Copy the code

The withUser method returns a UserDetailsBuilder object that uses the UserBuilder object described earlier internally.

A chain syntax like.withuser (“spring_user”).password(“password1”).roles(“USER”) can be implemented to set USER information

conclusion

Today we took a look at the user object mechanism and teased out the relationships between several classes. Below you can go into the source code with again. So that’s it for today, next time we’ll talk about authentication objects in the authentication system, and with the user’s processing class, we’ll definitely talk about how authentication is done. Come on, learn together!!

overtones

Thank you for reading, if you feel that you have learned something, please like, follow. Also welcome to have a question we comment below exchange

Come on! See you next time!

To share with you a few I wrote in front of a few SAO operation

Talk about different strategy patterns (Bookmarks)

Copy object, this operation is a little SAO!