[JAVA] [Introduction to Spring Boot] Authentication function with Spring Security

Purpose

For those who have finished working on the Spring Quickstart Guide, those who have started learning Spring Boot, and those who want to review it.

We will share what we have learned by actually working on the official guide Securing a Web Application.

Check the completed form. There is a top page, click here, スクリーンショット 2020-07-13 11.59.12.png

Go to the login page. Enter the username and password for the test user and click the Sign in button スクリーンショット 2020-07-13 11.59.27.png

You will be taken to a page that can only be viewed by authenticated people. You cannot access this screen if you are not logged in. スクリーンショット 2020-07-13 12.00.36.png

The development environment and the review so far are as follows.

Development environment


OS: macOS Mojave version 10.14.6
Text editor: Visual Studio Code (hereinafter VSCode)
Java: 11.0.2

QuickstartGuide Building a RESTful Web Service Consuming a RESTful Web Service Accessing Data with JPA Handling Form Submission Securing a Web Application

1. Start the Spring Boot project!

First, access spring initializr.

  1. Click the ADD DEPENDENCIES button to add Spring Web and Thymeleaf. 2.Artifact, Name changed to securing-web.
  2. Change Java to 11.

Then click the GENERATE button to download the Zip file.

スクリーンショット 2020-07-13 13.17.09.png

Extract the downloaded Zip file and you're ready to go.

2. Add code!

Open the previous folder with VS Code. We recommend installing the Java Extension Pack for extensions. It is said that you should install it.

スクリーンショット 2020-06-30 10.08.25.png

Let's create home.html!

Create a home.html file in src / main / resources / templates /.

スクリーンショット 2020-07-13 13.29.09.png

Add the code referring to the formula. It will be the top page.

home.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
  <head>
    <title>Spring Security Example</title>
  </head>
  <body>
    <h1>Welcome!</h1>

    <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
  </body>
</html>

The html tag part is for writing th: 〇〇 and sec: 〇〇 (the description method using thymeleaf and Spring Security tags becomes possible).

Now let's dig deeper into the description of thymeleaf in the added code.

thymeleaf is a template engine that can be handled by springboot. Described as th: 〇〇. [Thymeleaf tutorial] written in Japanese (https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html#thymeleaf%E3%81%AE%E7%B4%B9%E4%BB% There is also 8B)!

th:href

This tag is set in the href attribute of the a tag. The description method is th: href =" @ {} ". Specify the path in {}. This time it is / hello, so if you click the tag, it will transition to http: // localhost: 8080 / hello.

Let's create hello.html!

Create a hello.html file in src / main / resources / templates /.

スクリーンショット 2020-07-13 14.21.54.png

Add the code referring to the formula.

hello.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
  <head>
    <title>Hello World!</title>
  </head>
  <body>
    <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
    <form th:action="@{/logout}" method="post">
      <input type="submit" value="Sign Out"/>
    </form>
  </body>
</html>

th: inline is for expanding the value of a variable in the text of the tag. Enclose the variable you want to display in [[...]]. This time, it is $ {# httpServletRequest.remoteUser}, so the name of the authenticated user is displayed.

When the Sign Out button is pressed, you will be redirected to / login? Logout.

Let's create MvcConfig.java!

Create an MvcConfig.java file in src / main / java / com / example / securingweb /.

スクリーンショット 2020-07-13 14.43.27.png

Add the code referring to the formula.

MvcConfig.java


package com.example.securingweb;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/home").setViewName("home");
    registry.addViewController("/").setViewName("home");
    registry.addViewController("/hello").setViewName("hello");
    registry.addViewController("/login").setViewName("login");
  }

}

The ** @ Configuration ** annotation is added to the class so that various Spring settings can be performed in Java code. (Setting class) I have created an MvcConfig class that implements the WebMvcConfigurer interface and overrides the addViewControllers method.

registry.addViewController("/home").setViewName("home");

Instead of having another Controller and using the @GetMapping annotation to return the View name By the above description

When the URL is http: // localhost: 8080 / home, the template ** home.html ** will be referenced. It seems that the URL and template are mapped. Login.html will be implemented later.

Add Spring Security to pom.xml!

Add the following to pom.xml to use Spring Security.

Spring Security is a framework for adding security features to web applications. Provides comprehensive support for authentication, authorization, and protection against common abuse.

pom.xml


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
		
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>

スクリーンショット_2020-07-13_15_32_20.png

Let's create WebSecurityConfig.java!

Create a WebSecurityConfig.java file in src / main / java / com / example / securingweb /.

スクリーンショット 2020-07-13 15.48.47.png

Add the code referring to the formula.

WebSecurityConfig.java


package com.example.securingweb;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .antMatchers("/", "/home").permitAll()
        .anyRequest().authenticated()
        .and()
      .formLogin()
        .loginPage("/login")
        .permitAll()
        .and()
      .logout()
        .permitAll();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    String password = passwordEncoder().encode("password");

    auth.inMemoryAuthentication()
        .passwordEncoder(passwordEncoder())
        .withUser("user").password(password).roles("USER");
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
  }

}

We will dig deeper into the added code.

① Inheritance of @EnableWebSecurity and WebSecurityConfigurerAdapter classes

WebSecurityConfig.java


@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  //abridgement
}

Spring Security is enabled by adding the @EnableWebSecurity annotation. And it inherits an abstract class called WebSecurityConfigurerAdapter. Override the ** configure method ** in this class We will implement whether or not to restrict page access.

② Set page access restrictions

WebSecurityConfig.java


@Override
protected void configure(HttpSecurity http) throws Exception {
  http
    .authorizeRequests()
      .antMatchers("/", "/home").permitAll() //URLs that do not require access restrictions
      .anyRequest().authenticated()  //Other URLs require authentication. You cannot access it unless you are authenticated
      .and()
    .formLogin()
      .loginPage("/login") //No access restrictions on the login screen
      .permitAll() //No authentication required
      .and()
    .logout()
      .permitAll(); //No authentication required
}

Overriding ** configure method **. HttpSecurity is received as an argument, and it is a method for describing the settings for the part related to http request. Set whether authentication is required when logging in, logging out, or accessing other pages.

③ User settings to authenticate

The implementation of this part has been said to be deprecated if you follow the official guide. So it has a slightly different implementation.

WebSecurityConfig.java



@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//Encode password
String password = passwordEncoder().encode("password");

//Settings for in-memory authentication
auth.inMemoryAuthentication()
    .passwordEncoder(passwordEncoder())
    .withUser("user").password(password).roles("USER");
}

@Bean
public PasswordEncoder passwordEncoder() {
  return new BCryptPasswordEncoder();
}

** PasswordEncoder passwordEncoder () ** defines a method for hashing passwords. Then, the password of the string is hashed with String password = passwordEncoder (). Encode ("password"); .

AuthenticationManagerBuilder is a class that enables in-memory authentication.

python


//Settings for in-memory authentication
auth.inMemoryAuthentication()
    .passwordEncoder(passwordEncoder())
    .withUser("user").password(password).roles("USER");
}

We implement it here and set the user to authenticate.

Let's create login.html!

Create a login.html file in src / main / resources / templates /.

スクリーンショット 2020-07-14 10.45.45.png

Add the code referring to the formula. It will be the login page.

login.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
  <head>
    <title>Spring Security Example </title>
  </head>
  <body>
    <div th:if="${param.error}">
      Invalid username and password.
    </div>
    <div th:if="${param.logout}">
      You have been logged out.
    </div>
      <form th:action="@{/login}" method="post">
        <div><label> User Name : <input type="text" name="username"/> </label></div>
        <div><label> Password: <input type="password" name="password"/> </label></div>
        <div><input type="submit" value="Sign In"/></div>
      </form>
  </body>
</html>

There is a field to enter the User Name and Password. th: if =" $ {param.error} is the area displayed when user authentication fails. th: if =" $ {param.logout} is the area that will be displayed when you sign out (displayed after the Sign Out button is pressed in hello.html).

3. Let's run it!

Now that the application is ready to run, let's check.

Enter the following command in the terminal and press Enter.

Terminal


$ ./mvnw spring-boot:run

The top page is displayed.

スクリーンショット 2020-07-14 13.34.37.png

Click here to go to the login page. スクリーンショット 2020-07-14 13.34.52.png

Enter an appropriate User Name and Password and press the Sign In button. スクリーンショット 2020-07-14 13.37.30.png

The login page is redisplayed and the error message is also displayed. Next, enter ʻuser in Uesr Name and password` in Password and press the Sign In button.

スクリーンショット 2020-07-14 13.39.23.png

I was able to transition to a page that can only be viewed by authenticated people. スクリーンショット 2020-07-14 13.39.23.png

When you press the Sign Out button,

スクリーンショット 2020-07-14 13.41.36.png

You'll be redirected to the login page and you'll see a message.

Thank you for your hard work. done!

Reference site

** Deprecated alternative to User.withDefaultPasswordEncoder () ** ** [Spring Security has started] # 2 User Authentication ** ** "Hello World!" With Spring Security **

Recommended Posts

[Introduction to Spring Boot] Authentication function with Spring Security
Implemented authentication function with Spring Security ②
Implemented authentication function with Spring Security ③
Implemented authentication function with Spring Security ①
Achieve BASIC authentication with Spring Boot + Spring Security
Try to implement login function with Spring Boot
Introduction to Spring Boot ① ~ DI ~
Introduction to Spring Boot ② ~ AOP ~
Login function with Spring Security
Introduction to Spring Boot Part 1
Spring Boot Tutorial Using Spring Security Authentication
Authentication / authorization with Spring Security & Thymeleaf
Set Spring Security authentication result to JSON
[Introduction to Spring Boot] Form validation check
DB authentication with Spring Security & hashing with BCrypt
Implement paging function with Spring Boot + Thymeleaf
Introduction to Spring Boot x OpenAPI ~ OpenAPI made with Generation gap pattern ~
A new employee tried to create an authentication / authorization function from scratch with Spring Security
With Spring boot, password is hashed and member registration & Spring security is used to implement login function.
About Spring Security authentication
Hash passwords with Spring Boot + Spring Security (with salt, with stretching)
How to read Body of Request multiple times with Spring Boot + Spring Security
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
An introduction to Spring Boot + in-memory data grid
Try to automate migration with Spring Boot Flyway
I wanted to gradle spring boot with multi-project
Download with Spring Boot
Create Spring Cloud Config Server with security with Spring Boot 2.0
Introduction to Java development environment & Spring Boot application created with VS Code
Create login / logout function with Spring Security according to Spring official guide [For beginners]
Settings for connecting to MySQL with Spring Boot + Spring JDBC
Execute arbitrary processing after Basic authentication with Spring boot.
Automatically map DTOs to entities with Spring Boot API
Spring Boot with Spring Security Filter settings and addictive points
[Introduction to Spring Boot] Submit a form using thymeleaf
How to boot by environment with Spring Boot of Maven
Attempt to SSR Vue.js with Spring Boot and GraalJS
Try to work with Keycloak using Spring Security SAML (Spring 5)
Try Spring Boot from 0 to 100.
Generate barcode with Spring Boot
Hello World with Spring Boot
Implement GraphQL with Spring Boot
Java to play with Function
Get started with Spring boot
Introduction to Ratpack (7) --Guice & Spring
Run LIFF with Spring Boot
SNS login with Spring Boot
File upload with Spring Boot
Spring Boot starting with copy
Hello World with Spring Boot
Getting Started with Spring Boot
Try using Spring Boot Security
Create microservices with Spring Boot
Send email with spring boot
About the function of Spring Boot due to different versions
Extract SQL to property file with jdbcTemplate of spring boot
Connect to database with spring boot + spring jpa and CRUD operation
Flow until output table data to view with Spring Boot
I tried to get started with Swagger using Spring Boot
Implement a simple Rest API with Spring Security & JWT with Spring Boot 2.0