Springboot spring security core component authentication process user permission information acquisition detailed explanation

Time:2021-11-29

preface

Spring security is a security framework. You can simply think of spring security as a security barrier between users and spring applications. Every web request must be authenticated and authenticated by spring security

Springboot spring security core component authentication process user permission information acquisition detailed explanation

Core components

SecurityContextHolder

Securitycontextholder holds the security context(security context). Who is the user of the current operation, whether the user has been authenticated, what role rights he has, etc. are saved in the securitycontextholder. Securitycontextholder uses ThreadLocal policy by default to store authentication information. noticeThreadLocalThis means that this is a strategy bound to threads. In the web environment, spring security automatically binds the authentication information to the current thread when the user logs in, and automatically clears the authentication information of the current thread when the user exits

Look at the source code. He has static methods

//Get context
  public static SecurityContext getContext() {
        return strategy.getContext();
    }
  //Clear context  
  public static void clearContext() {
        strategy.clearContext();
    }
SecurityContextHolder.getContext().getAuthentication().getPrincipal()

getAuthentication()Authentication information is returned,getPrincipal()Identity returned

UserDetailsIt is an interface for spring to encapsulate identity information

SecurityContext

Security context, mainly holdingAuthenticationObject. If the user is not authenticated, the authentication object will be empty. Look at the source code

package org.springframework.security.core.context;

import java.io.Serializable;
import org.springframework.security.core.Authentication;

public interface SecurityContext extends Serializable {
    Authentication getAuthentication();

    void setAuthentication(Authentication var1);
}

Authentication

Authentication object, which mainly contains user details(UserDetails)And the information required for user authentication, such as user name, password, member me token, or digest hash value submitted by the user, use different authentication methodsAuthenticationrealization

Look at the source code

package org.springframework.security.core;

import java.io.Serializable;
import java.security.Principal;
import java.util.Collection;

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    Object getCredentials();

    Object getDetails();

    Object getPrincipal();

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
  1. AuthenticationIt is an interface in the spring security package and directly inherits from the principal class, which is located in the java.security package. It can be seen that authentication is the highest level of identity / authentication abstraction in spring security. From this top-level interface, we can get the user’s permission information list, password, user details, user identity information and authentication information.

  2. getAuthorities(), permission information list. By default, it is some implementation classes of the grantedauthority interface. It is usually a series of strings representing permission information.

  3. getCredentials(), password information, the password string entered by the user, is usually removed after authentication to ensure security.

  4. getDetails(), details. The implementation interface in a web application is usually webauthenticationdetails, which records the visitor’s IP address and sessionid value.

  5. getPrincipal(), knock on the blackboard!!! The most important identity information, in most cases, is the implementation class of the userdetails interface, which is also one of the common interfaces in the framework

be carefulGrantedAuthorityThis interface represents the permission (or role) information of the current user. This information is the responsibility of the authorized objectAccessDecisionManagerTo use and determine whether end users can access aresources(URL or method call or domain object). This object is not used for authentication

UserDetails

This interface specifies the fields of user details, such as user name, password, whether the account expires, whether it is locked, etc. In spring security, it is generally necessary to obtain the information of the currently logged in user on this interfaceextendTo connect users of their own systems

Look at the source code

package org.springframework.security.core.userdetails;

import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

UserDetailsService

This interface provides only one interfaceloadUserByUsername(String username), this interface is veryImportant,Generally, we passextendThis interface is used to display and obtain our user information. The user name and password passed during user login are also verified through the user name and password found here, but the real verification is not here, but byAuthenticationManageras well asAuthenticationProviderResponsible. It should be emphasized that if the user does not exist, it should not be returnedNULLInstead of throwing an exceptionUsernameNotFoundException

Look at the source code

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

Principle of spring security security identity authentication process

  1. The user name and password are obtained by the filter and encapsulated intoAuthentication, usuallyUsernamePasswordAuthenticationTokenThis implementation class.

  2. AuthenticationManagerThe identity manager is responsible for verifying thisAuthentication

  3. After successful certification,AuthenticationManagerThe identity manager returns a full of information (including the permission information, identity information and details mentioned above, but the password is usually removed)Authenticationexample.

  4. SecurityContextHolderThe security context container populates step 3 with informationAuthentication, passSecurityContextHolder.getContext().setAuthentication()Method, set to it.

AuthenticationManager

Friends who come into contact with spring security for the first time believe that they will be confused by so many similar spring authentication classes such as AuthenticationManager, providermanager and authenticationprovider, but you can understand their relationship and the designer’s intention as long as you comb them a little.

AuthenticationManager(Interface) is authentication relatedCore interface, which is also the starting point for initiating authentication, because in actual needs, we may allow users to log in with user name + password, email + password, mobile phone number + password, and even allow users to log in with fingerprint (there are such operations? I didn’t expect it). ThereforeAuthenticationManagerGenerally, it is not directly certified,

AuthenticationManagerCommon implementation classes of interfaceProviderManagerOne will be maintained internallyList<AuthenticationProvider>List to store a variety of authentication methods. In fact, this is the application of delegate mode.

In other words, there is always only one authentication entry for the core:AuthenticationManager, different authentication methods: user name + password(UsernamePasswordAuthenticationToken), e-mail + password, mobile phone number + password login corresponds to threeAuthenticationProvider。 This makes it much easier to understand

Userdetails and userdetailsservice

UserDetails

It’s constantly mentioned aboveUserDetailsThis interface represents the most detailed user information. This interface covers some necessary user information fields. We generally need to extend it.

It andAuthenticationThe interfaces are very similar. For example, they all have username and authorities. Distinguishing them is also one of the key contents of this article.

Getcredentials() in authentication and getpassword() in userdetailsThe former is the password certificate submitted by the user, and the latter is the user’s correct password. The authenticator is actually a comparison between the two. Getauthorities () in authentication is actually passed by getauthorities () of userdetails. Remember the getuserdetails () method in the authentication interface? The userdetails user details are filled in after going through the authenticationprovider.

UserDetailsService

The responsibilities of userdetailsservice and authenticationprovider are often confused. Userdetailsservice is only responsible for loading user information from specific places, such as database, redis cache, interface, etc

Springboot spring security core component authentication process user permission information acquisition detailed explanation

Global access to user information

  1. Obtain user information by injecting the principal interface

During the running process, spring will inject username, password, authentication and token into the principal interface, which can be obtained and used directly in the controller

@GetMapping("/home")
    @Apioperation ("user center")
    public Result getUserHome(Principal principal) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=(UsernamePasswordAuthenticationToken)principal;
        return ResultResponse.success(usernamePasswordAuthenticationToken.getPrincipal());
    }
  1. How to annotate parameters using @ authenticationprincipal
@GetMapping("/home")
    @Apioperation ("user center")
    public Result getUserHome(@AuthenticationPrincipal cn.soboys.kmall.security.entity.User user ) {
        return ResultResponse.success(user);
    }
  1. Global context acquisition

It is a common requirement to obtain the user name of the current user. In fact, spring security has implemented it for us in the implementation class in authentication. Therefore, there are simpler ways to obtain the user name of the current user as follows

@RestController
public class HelloController {
 
    @GetMapping("/hello")
    public String hello() {
        Return "current login user:" + securitycontextholder. Getcontext(). Getauthentication(). Getname();
    }
}
  1. Get the userdetails instance of the currently logged in user, and then convert it to the user-defined user entity class user, so that you can get the user’s ID and other information
@RestController
public class HelloController {
 
    @GetMapping("/hello")
    public String hello() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User)principal;
        Return "current login user information:" + user. Tostring();
    }
}
  1. Get user information in asynchronous method

By default, spring security cannot obtain the current login user’s in the method using @ async annotation. If you want to get the current login user in the @ async method, you need to callSecurityContextHolder.setStrategyNameMethod and set related policies

reference resources

  1. Spring security obtains the login user in the @ async asynchronous method
  2. Spring Security