“This is the 16th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Author: Tangyuan

Personal blog: Javalover.cc

Introduction to the

SpringSecurity has a variety of authentication mechanisms, such as username/password based authentication, OAuth2.0 based authentication (OAuth deprecated)…

There are different authentication modes based on user name and password, for example:

  • Form Login, Form Login authentication (singleton applications such as SpringMVC)
  • Basic Authentication, Basic HTTP Authentication (front-end and back-end separated applications)
  • [Deprecated] Digest Authentication (Deprecated. This Authentication mode is no longer used because its encryption is insecure, such as MD5 encryption. Now the more secure encryption methods are BCrypt, etc.)

This section introduces the second method: basic authentication

directory

  1. Maven configuration
  2. Security configuration
  3. The controller controller
  4. A web interface
  5. Is up and running

The body of the

Before we begin, there are two words to understand

  • Authenticate: logs in to the system using user names or passwords. It’s like a gate into a scenic spot
  • Authorize: is after logging into the system, verify whether the user has the authority to operate a module, this process is authorization; After entering the scenic area, each charging area, only pay the money (have authority), can enter the designated area;

Project background: Spring Boot + Vue

The project structure is as follows: the SRC /main directory is the back-end interface, and the SRC/Web directory is the front-end interface

1. The maven configurations


      
<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">
    <parent>
        <artifactId>spring-boot-demo</artifactId>
        <groupId>com.jalon</groupId>
        <version>0.0.1 - the SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>demo-spring-security</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <! -... other dependency elements ... -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
Copy the code

2. The security configuration

There are two main parts:

  • Authenticate authentication configuration: configure the user name, password, and role (stored in memory for simplicity).
  • Authorize Configuration: Sets the permissions of each role, that is, the pages that can be accessed
@Configuration
@EnableWebSecurity
public class CustomConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/ * *");
    }

    // Global configuration: username + password, role (memory based)
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("javalover").password( passwordEncoder().encode("123456"))
                .authorities("ROLE_USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                // httpBasic means that authentication is performed not through a login form, but through HTTP requests
                .httpBasic();
    }

    // The password encryptor must be injected, or the default password encryptor will be displayed
    @Bean
    public PasswordEncoder passwordEncoder(a){
        return newBCryptPasswordEncoder(); }}Copy the code

3. Controller Controller

The controller’s main job is to handle requests, and here we write only one method to test the difference between authenticated and unauthenticated

@RestController
public class UserController {

    @GetMapping("/home")
    public String home(a){
        return "home"; }}Copy the code

4. Command line request test

Let’s test the above interface;

Execute the following request command: Do not pass the username/password

curl -i http://localhost:8090/home
Copy the code

Not surprisingly, the 401 unauthorized error is reported as follows:

HTTP/1.1 401
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Set-Cookie: JSESSIONID=37DBDC431DCA48BEBBEE1A65B82582C1; Path=/; HttpOnly
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 12 Nov 2021 09:31:09 GMT

{"timestamp":"The 2021-11-12 T09:31:09. 788 + 00:00"."status": 401,"error":"Unauthorized"."message":""."path":"/home"}
Copy the code

Next, we pass in the username/password set in the configuration (Javalover /123456) as follows:

curl -i --user javalover:123456 http://localhost:8090/home
Copy the code

If 200 is returned and the result is HOME, the request is successful, as shown below:

HTTP/1.1 200 Vary: Origin Vary: access-control-request-method Vary: access-control-request-headers set-cookie: JSESSIONID=1A81AF17E7EB380E16F0E8854DA59452; Path=/; HttpOnly X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Content-Type: text/plain; charset=UTF-8 Content-Length: 4 Date: Fri, 12 Nov 2021 09:31:44 GMT homeCopy the code

If you do not use curl to make the request, the browser will automatically pop up a login window asking you to fill in your username and password, as shown below:

We fill in thejavalover/123456, you can see the returned data:

5. Vue interface request test

Helloworld.vue = helloWorld.vue = helloWorld.vue

<template> <div> < button@click ="home"> home </button> </div> </template> <script> import axios from 'axios' export default { data: function (){ return { axiosInstance: {} } }, mounted() { this.axiosInstance = axios.create({ baseURL: 'http://localhost:8090', auth: { username: 'javalover', password: '123456')}}}, methods:{ home(){ this.axiosInstance.get('/home').then(res=> { console.log('success') console.log(res) }).catch(err=>{ console.log('fail') console.log(err) }) } } } </script>Copy the code

Next, we start vueyarn Run Serve, visit the main interface http://localhost:8080/, click the home page: you can see that success is printed

Similarly, if we remove the username/password configuration from helloworld.vue, we will print fail and declare 401:

conclusion

SpringSecurity’s basic authentication is the same as forms authentication. The code on the back end is pretty much the same except for the configuration.

The core of both of these is user name/password authentication, but the scenarios are different:

  • Form Login: applies to single applications

  • Basic Authentication: Basic HTTP Authentication, applicable to applications where the front and back ends are separated

Source code address: Demo-spring-security-basic-auth