It is a continuation from here. This time, we will create a login page and an administrative user creation page.
Create a form to be used on the login page and user creation page.
D:\JAVA\Project\securitySample\src\main\java\com\example
└─form
  └─AuthForm.java
AuthForm.java
AuthForm.java
package com.example.web.form;
import javax.validation.constraints.Size;
import lombok.Data;
@Data
public class AuthForm {
    private String userId;
    @Size(min=3, max=255)
    private String password;
    private String userNameJP;
    private String sectionNameJP;
    private Boolean enabled;
    private String[] authority;
}
Create business logic related to user registration.
D:\JAVA\Project\securitySample\src\main\java\com\example
└─service
  ├─AuthService.java
  └─AuthServiceImpl.java
AuthService.java
AuthService.java
package com.example.service;
import java.util.List;
import com.example.persistence.entity.UserInfo;
import com.example.web.form.AuthForm;
public interface AuthService {
	void insertAdmin(AuthForm authForm);
	void insertUser(AuthForm authForm);
	void updateUser(AuthForm authForm);
	void deleteUser(String id);
	Integer adminCheck();
	List<UserInfo> findUserAll();
	AuthForm userRegById(String id);
}
AuthServiceImpl.java
AuthServiceImpl.java
package com.example.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.example.persistence.entity.UserInfo;
import com.example.persistence.entity.UserRoles;
import com.example.persistence.repository.UserInfoRepository;
import com.example.persistence.repository.UserRolesRepository;
import com.example.web.form.AuthForm;
@Service
public class AuthServiceImpl implements AuthService {
	@Autowired
	UserInfoRepository userInfoRepository;
	@Autowired
	UserRolesRepository userRolesRepository;
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
	public void insertAdmin(AuthForm authForm) {
		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		UserInfo userInfo = new UserInfo();
		UserRoles userRoles = new UserRoles();
		List<UserRoles> userRokesList  = new  ArrayList<UserRoles>();
		userInfo.setUserId(authForm.getUserId());
		userInfo.setPassword(encoder.encode( authForm.getPassword() ));
		userInfo.setUserNameJP("Administrator");
		userInfo.setSectionNameJP("Administrator");
		userInfo.setEnabled(true);
		userRoles.setUserId(authForm.getUserId());
		userRoles.setAuthority("ROLE_ADMIN");
		userRokesList.add(userRoles);
		userInfo.setUserRolesList(userRokesList);
		userInfoRepository.insert(userInfo);
		userInfo.getUserRolesList().forEach(s -> {
			userRolesRepository.insert(s);
		});
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
	public void insertUser(AuthForm authForm) {
		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		UserInfo userInfo = new UserInfo();
		userInfo.setUserId(authForm.getUserId());
		userInfo.setPassword(encoder.encode( authForm.getPassword() ));
		userInfo.setUserNameJP(authForm.getUserNameJP());
		userInfo.setSectionNameJP(authForm.getSectionNameJP());
		userInfo.setEnabled(true);
		userInfoRepository.insert(userInfo);
		List<String> authorityList = new ArrayList<String>(Arrays.asList(authForm.getAuthority()));
		authorityList.add("ROLE_USER");
		authorityList.forEach(s -> {
			UserRoles userRoles = new UserRoles();
			userRoles.setUserId(authForm.getUserId());
			userRoles.setAuthority(s);
			userRolesRepository.insert(userRoles);
		});
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public Integer adminCheck() {
		return userRolesRepository.adminCheck();
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
	public void updateUser(AuthForm authForm){
		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		UserInfo userInfo = new UserInfo();
		userInfo.setUserId(authForm.getUserId());
		userInfo.setPassword(encoder.encode(authForm.getPassword()));
		userInfo.setUserNameJP(authForm.getUserNameJP());
		userInfo.setSectionNameJP(authForm.getSectionNameJP());
		userInfo.setEnabled(authForm.getEnabled());
		userInfoRepository.update(userInfo);
		userRolesRepository.delete(authForm.getUserId());
		List<String> authorityList = new ArrayList<String>(Arrays.asList(authForm.getAuthority()));
		authorityList.add("ROLE_USER");
		authorityList.forEach(s -> {
			UserRoles userRoles = new UserRoles();
			userRoles.setUserId(authForm.getUserId());
			userRoles.setAuthority(s);
			userRolesRepository.insert(userRoles);
		});
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
	public void deleteUser(String id) {
		userInfoRepository.delete(id);
		userRolesRepository.delete(id);
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<UserInfo> findUserAll() {
		return userInfoRepository.findUserAll();
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public AuthForm userRegById(String id){
		AuthForm authForm = new AuthForm();
		Optional<UserInfo> userInfoOpt = userInfoRepository.selectDetailByUserId(id);
		userInfoOpt.ifPresentOrElse(userInfo -> {
			authForm.setUserId(userInfo.getUserId());
			authForm.setPassword(userInfo.getPassword());
			authForm.setUserNameJP(userInfo.getUserNameJP());
			authForm.setSectionNameJP(userInfo.getSectionNameJP());
			authForm.setEnabled(userInfo.getEnabled());
			String[] arrayAuthority = new String[userInfo.getUserRolesList().size()];
			Integer i = 0;
			for (UserRoles ur : userInfo.getUserRolesList()) {
				arrayAuthority[i] = ur.getAuthority();
				i++;
			}
			authForm.setAuthority(arrayAuthority);
		},null);
		return authForm;
	}
}
Create a controller for the login page and admin user creation page.
D:\JAVA\Project\securitySample\src\main\java\com\example
└─controller
  ├─AuthController.java
  └─AdminRegController.java
AuthController.java
AuthController.java
package com.example.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.service.AuthService;
@Controller
@RequestMapping("/auth")
public class AuthController {
	@Autowired
	AuthService authService;
	@GetMapping("/login")
    public String loginGet(Model model) {
		if(authService.adminCheck() <= 0) {
        	return "redirect:/adminReg/index";
        }
		return "auth/login";
    }
	@GetMapping("/403")
    public String index403(Model model) {
		return "auth/403";
    }
	@GetMapping("/login-error")
    public String loginErrorGet(Model model) {
        model.addAttribute("loginError", true);
        return "auth/login";
    }
}
AdminRegController.java
AdminRegController.java
package com.example.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.service.AuthService;
import com.example.web.form.AuthForm;
@Controller
@RequestMapping("/adminReg")
public class AdminRegController {
	@Autowired
	AuthService authService;
	@GetMapping("/index")
    public String indexGet(Model model) {
		//Only one ADMIN role user
        if(authService.adminCheck() > 0) {
        	return "redirect:registered";
        }
		model.addAttribute("authForm", new AuthForm());
        return "adminReg/index";
    }
	@PostMapping("/index")
    public String indexPost(Model model,
    		@Valid AuthForm authForm, BindingResult bindingResult, HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
        	model.addAttribute("signupError", true);
            return "adminReg/index";
        }
        try {
        	authService.insertAdmin(authForm);
        } catch (DataIntegrityViolationException e) {
            model.addAttribute("signupError", true);
            return "adminReg/index";
        }
        return "adminReg/done";
    }
	@GetMapping("/registered")
    public String registered(Model model) {
        return "adminReg/registered";
    }
}
Set the redirect destination on the authentication screen when the route is accessed.
RootController.java
package com.example.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class RootController {
    @GetMapping("/")
    public String root() {
        return "redirect:auth/login";
    }
}
Create a view of the login page and admin user creation page.
D:\JAVA\Project\securitySample\src\main\webapp\WEB-INF\templates
├─adminReg
| ├─done.html
| ├─index.html
| └─registered.html
├─auth
| ├─403.html
| └─login.html
└─fragment
  └─frag01.html
Use template fragments to componentize common parts.
fragment/frag01.html
frag01.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<!--HTML header-->
<head th:fragment="htmlhead" th:remove="tag">
	<meta charset="UTF-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
</body>
</html>
adminReg/done.html
done.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:include="fragment/frag01 :: htmlhead"></head>
	<title>Administrator ID registration page completed</title>
</head>
<body>
	<h1>I registered the administrator ID.</h1>
	<a th:href="@{/auth/login}">Top</a>
</body>
</html>
adminReg/index.html
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>Administrator ID registration page</title>
</head>
<body>
	<h1>Administrator ID registration page</h1>
	<form method="post" action="#" th:action="@{index}" th:object="${authForm}">
		<div th:if="${signupDone}">
			<em>Has registered.</em>
		</div>
		<div th:if="${signupError}">
			<em>I couldn't register.</em>
		</div>
		<div>
			<label for="userId">Login ID</label>:
			<input type="text" autofocus="autofocus" th:field="*{userId}">
		</div>
		<div>
			<label for="password">password</label>:
			<input type="password" th:field="*{password}">
			<em th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password Error</em>
		</div>
		<div>
			<button type="submit">Registration</button>
		</div>
	</form>
</body>
</html>
adminReg/registered.html
registered.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>Administrator ID registration page</title>
</head>
<body>
	<h1>The administrator ID has been registered.</h1>
	<a th:href="@{/auth/login}">Top</a>
</body>
</html>
auth/403.html
403.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org" th:with="lang=${#locale.language}" th:lang="${lang}"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>Error page</title>
</head>
<body>
	<div>
		<h1>I'm sorry. An error has occurred.</h1>
	</div>
</body>
</html>
auth/login.html
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>Login page</title>
</head>
<body>
	<h1>Login page</h1>
	<form method="post" action="#" th:action="@{/login}">
		<div th:if="${loginError}">
			<em>I couldn't log in. Please check your login ID and password.</em>
		</div>
		<div>
	        <label for="uername">Login ID</label>:
	   		<input type="text" id="username" name="username" autofocus="autofocus">
		</div>
		<div>
	    	<label for="password">password</label>:
			<input type="password" id="password" name="password">
		</div>
		<div>
			<button type="submit">Login</button>
		</div>
	</form>
</body>
</html>
If you make it so far, you will be able to check the operation. Please compile and run it. You will be able to register as an administrative user.
Next, create a user-created page. That's it.
Recommended Posts