Spring Security Oauth2 architecture learning

1. Basic concepts

At present, the third version of auth.0, which is the most widely used authentication standard for users, provides a safe and easy-to-use version of auth. Auth for any user

Analyze the process of using vx authentication for websites:

1. First of all, if users want to access resources, they need to be authenticated and use third-party authentication, such as vx,qq, Sina, etc

2. If the user confirms to use the third-party authentication, he needs to request the authorization code from the corresponding third party. After obtaining the authorization code, he can use the obtained authorization code to authorize the server to request a token

3. The server verifies the token. If successful, it will grant the corresponding permission to access the resource and obtain the corresponding resource or personal information

Oauth2 this is for the convenience of safe users (third parties) to log in.
It must have been silly to hear oauth2 this word at first. What is this for authentication? For certification? For authorization? Is it the same thing as shiro(java)?

In fact, oauth is a process. We write code according to the requirements of this process

oauth has an authorization server. It is used as user authentication. For the server, only one oauth authorization server needs to be implemented. For users (calling the R & D of authorization and authentication), they only need to send a request according to the process.

Oauth has four entities. Let's use QQ to log in to microblog as an example.
Resource owner (ordinary user)

Resource server is the background server of QQ (get account, nickname, avatar, etc.).

Client microblogging is the platform

The authorization server authenticates QQ & for authorization.

oauth has four ways. The purpose is not to expose the password to third parties. (i.e. do not expose QQ account and password to microblog)
1. authorization code is also the version with the highest security level. It supports refresh token, which is generally used for microblog QQ login.

2. password credentials supports refresh token, which has a low security level. Who knows if the client will steal your password. General internal use

3. The simplified mode implicit does not support refresh token, which does not get the code. The request gives the token, but the advantage of not getting it

4. client credentials in client mode does not support refresh token, which is used by trusted internal clients. Generally used between internal platforms

Note: client_id   client_secret is used by oauth server to authenticate clients.

Each method is described in detail below. Let's not talk about the simplified model.
 

1. Authorization code mode

Authorization code mode is to obtain double verification of verification code and token in the authorization server, and then authorize access

1) Add dependency:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>spring-sercrity-student</groupId>
    <artifactId>spring-sercrity-myself</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
    </properties>



    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-oauth2 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

        <!--When oauth2 An unreadable exception occurred during project startup. Add this dependency-->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>


        <!--spring cloud integration security frame-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-security -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>


        <!-- web modular -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


    </dependencies>


</project>

Add spring cloud dependency, and spring cloud also integrates security and oauth2 framework



2) Create securityconfig:

    /**
     * Authorization framework configuration class
     */
    @Configuration
    //Indicates that webSecurity is started
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                   //Release oauth authentication, login authentication, user exit
                    .antMatchers("/oauth/**", "/login/**", "logout/**").permitAll()
    
                    //Intercept all requests that have not been released
                    .anyRequest().authenticated()
                    .and()
    
                    //Release all forms after certification
                    .formLogin().permitAll();
        }
    
        //Returns an encryptor
        @Bean
        public PasswordEncoder getPw() {
            return new BCryptPasswordEncoder();
        }
    }

3) Custom user information wrapper class

/**
 * User information packaging
 */
public class User implements UserDetails {

    //user name
    private String userName;

    //User password
    private String password;

    //User rights
    private List<GrantedAuthority> authorities;

    public User(String userName, String password, List<GrantedAuthority> authorities) {
        this.userName = userName;
        this.password = password;
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

4) Custom authentication class

/**
 * Custom authentication
 */
@Service
public class UserService implements UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String encodePw = passwordEncoder.encode("123");

     return new User(username,encodePw, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

This is just a demonstration. The actual password should be queried from the database for verification

5) Configure authorization server

/**
 * Authorization server configuration
 *
 * @author Qin Yang
 * @version 1.0
 */
@Configuration
//Indicates that authorization server configuration is enabled
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //It's only temporarily dead here. Normally, you need to authorize the server to register
                //Configure Client id
                .withClient("admin")

                //Configure client security
                .secret(passwordEncoder.encode("Vermouth2022"))

                //Set Token expiration time
                .accessTokenValiditySeconds(3600)

                //Redirect address, which is used to jump after successful authorization
                .redirectUris("http://www.baidu.com")
                //Scope of authorization, which part of the content to read
                .scopes("all")
                //Authorization type
                .authorizedGrantTypes("authorization_code");
    }
}

The client id and key obtained here will be verified at the same time during the second token verification!!!

6) Configure resource server

/**
 * Resource service configuration
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .requestMatchers()

                //Release the corresponding resources to be obtained
                .antMatchers("/user/**");
    }


}
    

When the token is verified successfully, the required functions are released

Specific operation process:

This is just a simulated login with authorization code. In fact, we usually go to vx this third party to obtain permission, so we also access their authorization server and resource manager, and this is to understand the process

When a user needs third-party authorization, we will use oauth protocol, and let the user scan or log in or face recognition to authenticate the user's identity, and send these authentication information to the authorization server

Authorization request: http://localhost:8080/oauth/authorize?response_type=code&client_id=admin&redirect_uri=http://www.baidu.com&scope=all

The url information here must be consistent with that defined in the authorization server, otherwise an error will be reported

/oauth / is the interface of our authorization framework

/Authorize means to authorize and request a verification code. The client id is admin. After success, jump to Baidu. The requested permission range is all

When we visit, it will automatically jump to the login interface and let us authenticate

 

After entering the account password / scanning the code, you will successfully enter our authorized page

 

Approve means to agree to the authorization and Dent means to refuse

After agreeing, we jump to the designated page

Look carefully, the url of the page contains a code, and its value is a verification code returned by our authorization server

When we get the verification code, we need to go to the authorization server for verification

To send messages with post requests, we use postman

Use the verification code for authentication, and input the client id we wrote in the authorization server. This should be registered under normal circumstances. It is written to death for demonstration

At the same time, the parameters required by the authorization server and the returned verification code should be carried in the request body

After clicking send, we get a token and some information returned by the authorization server

{
    "access_token": "5afbda45-62aa-4345-bd20-a4e647356cf2",
    "token_type": "bearer",
    "expires_in": 3599,
    "scope": "all"
}

After you get the token, you can access the resources we need. Take this token to make a request

After submitting, we will access the functions we need, and then get the corresponding resources. This is the authorization code mode

Tags: Java Back-end Spring Security

Posted by kickassamd on Sat, 16 Apr 2022 22:37:27 +0930