[JAVA] Spring Boot Tutorial Using Spring Security Authentication

I created a web page with a secure form by referring to the official Spring Boot tutorial (Protecting Web Applications).

environment

Maven 3.6.3 (OK for Maven 3.2 or later) OS: macOS Mojave version 10.14.6 Text editor: VSCode Java: 11.0.2

Create

Open Spring Initializr and create a foundation with the following contents. This time, we will add "Spring Web" and "Thymeleaf" as dependencies. スクリーンショット 2020-07-15 11.17.56.png

Unzip the resulting zip file and open it in an editor.

Let's check pom.xml. The contents of the automatically created pom file are as follows.

pom.xml


<?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 https://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.2.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>securing-web</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>securing-web</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

First, let's create a web application that is not protected by anything. The structure is as simple as displaying the home screen and "Hello World".

Create from the home screen. Create a home.html file under src / main / resources / templates. The contents are as follows.

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>

Next, create a hello screen. Create a hello.html file under src / main / resources / templates. The contents are as follows.

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>Hello world!</h1>
    </body>
</html>

Except for the html tag, it is a normal hrml. This will be edited again when implementing security.

Next, create an MvcConfig.java file under src / main / java / com / example / securingweb. The contents are as follows.

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 WebMvcConfigurer class inherited by the MvcConfig class overrides the addViewControllers method, so if you create such a Config class, you can implement the MVC configuration without creating a controller.

@Configuration is to allow you to configure various Spring settings. Also, in the Configuration class, add @Configuration to the class.

Now let's run the app. Nothing is secure at this point.

Run

Execute the following command.

./mvnw spring-boot:run

Once started, try opening http: // localhost: 8080 / hello in your browser. You should get to the hello screen without logging in.

Set Spring Security

Now, let's prevent users who are not logged in from displaying the hello screen.

With the current specifications, when the user clicks the link on the home screen, it immediately goes to the hello screen. Let's use Spring Security to change this so that it only appears after login.

Add the following dependencies to the pom file.

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>

Next, create a WebSecurityConfig.java file under src / main / java / com / example / securingweb with the following contents.

WebSecurityConfig.java


package com.example.securingweb;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
                                // "/", "/home"Is accessible to all users
				.antMatchers("/", "/home").permitAll()
                                //Authentication is required for other access
				.anyRequest().authenticated()
				.and()
                        //Login and logout are accessible to all users
			.formLogin()
				.loginPage("/login")
				.permitAll()
				.and()
			.logout()
				.permitAll();
	}

	@Bean
	@Override
	public UserDetailsService userDetailsService() {
		UserDetails user =
                         //Specify default username and password
			 User.withDefaultPasswordEncoder()
				.username("user")
				.password("password")
				.roles("USER")
				.build();

		return new InMemoryUserDetailsManager(user);
	}
}

@EnableWebSecurity It is an annotation that can use the security function.

permitAll() A method that allows access to all users. On the contrary, it does not allow anonymous access.

authenticated() This is a method for requesting authentication.

UserDetailsService overrides the UserDetailsService class to specify user settings.

Now only the logged-in user can go to the hello screen.

Next, create a login page. Create a login.html file under src / main / resources / templates.

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>

$ {param.error} and $ {param.logout} get the parameters of error and logout. If error is true, an error message is displayed, and if logout is true, a logout message is displayed.

Finally, display your current username so you can sign out. To do this, greet the current user in hello.html and have them show the signout form.

Now, edit hello.html to the following contents.

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 
//Get the user name and display it on the screen
[[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

The Sign Out form will POST to / logout. When you log out, you will be redirected to / login? Logout.

Finally, I'll add a little to SecuringWebApplication.java for running the app. Edit SecuringWebApplication.java under src / main / java / com / example / securingweb to the following contents.

SecuringWebApplication.java


package com.example.securingweb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SecuringWebApplication {

	public static void main(String[] args) throws Throwable {
		SpringApplication.run(SecuringWebApplication.class, args);
	}

}

Run again

Try starting the app with the following command.

./mvnw spring-boot:run

Once started, open http: // localhost: 8080. Click the link to go to the first page. スクリーンショット 2020-07-16 11.01.08.png

Click here to move to the login screen. Type ʻuser in User Name and password` in Password. スクリーンショット 2020-07-16 11.02.54.png

I was able to log in.

スクリーンショット 2020-07-16 11.03.48.png

If you enter different ones for User Name and Password, they will be played properly. スクリーンショット 2020-07-16 11.03.21.png

Click the Sign Out button to revoke your authentication and return to the login page with a logout message. スクリーンショット 2020-07-16 11.04.07.png

Recommended Posts

Spring Boot Tutorial Using Spring Security Authentication
Try using Spring Boot Security
Achieve BASIC authentication with Spring Boot + Spring Security
About Spring Security authentication
Try LDAP authentication with Spring Security (Spring Boot) + OpenLDAP
[Introduction to Spring Boot] Authentication function with Spring Security
Spring Boot tutorial task schedule
Spring Security usage memo Authentication / authorization
Spring Boot + Java + GitHub authentication login
Use Basic Authentication with Spring Boot
Implemented authentication function with Spring Security ②
Implemented authentication function with Spring Security ③
Implemented authentication function with Spring Security ①
Learn Spring Security authentication processing architecture
Authentication / authorization with Spring Security & Thymeleaf
Part 1: Try using OAuth 2.0 Login supported by Spring Security 5 with Spring Boot
Set Spring Security authentication result to JSON
DB authentication with Spring Security & hashing with BCrypt
Try using Spring Boot with VS Code
Spring Boot @WebMvcTest test enables Spring Security default security
Asynchronous processing with Spring Boot using @Async
[Tutorial] Spring Batch
Challenge Spring Boot
Spring Boot Form
Spring Boot Memorandum
gae + spring boot
Hash passwords with Spring Boot + Spring Security (with salt, with stretching)
[FCM] Implementation of message transmission using FCM + Spring boot
Create a Spring Boot application using IntelliJ IDEA
[Java / Spring Boot] Spring security ④ --Implementation of login process
[Java / Spring Boot] Spring security ⑤ --Implementation of logout processing
Add your own authentication items with Spring Security
Apply Twitter Bootstrap 4 to Spring Boot 2 using Webjars
Create Spring Cloud Config Server with security with Spring Boot 2.0
Create a portfolio app using Java and Spring Boot
Testing JPA entities and repositories using Spring Boot @DataJpaTest
Execute arbitrary processing after Basic authentication with Spring boot.
Try using DI container with Laravel and Spring Boot
SPRING BOOT learning record 01
[I tried] Spring tutorial
[Note] Configuration file when using Logback with Spring Boot
Spring Boot + Heroku Postgres
Spring boot memo writing (1)
Try using OpenID Connect with Keycloak (Spring Boot application)
Spring Security usage memo: Cooperation with Spring MVC and Boot
[JUnit 5 compatible] Write a test using JUnit 5 with Spring boot 2.2, 2.3
First Spring Boot (DI)
SPRING BOOT learning record 02
Spring Boot2 cheat sheet
Spring Boot with Spring Security Filter settings and addictive points
Spring Boot exception handling
Implement a simple Rest API with Spring Security with Spring Boot 2.0
Spring Boot Servlet mapping
Spring boot development-development environment-
Spring Boot learning procedure
Spring Security causes 403 forbidden
[Introduction to Spring Boot] Submit a form using thymeleaf
Learning Spring Boot [Beginning]
Spring boot memo writing (2)
Spring Boot 2.2 Document Summary
Test field-injected class in Spring boot test without using Spring container