본문 바로가기

Programming/Spring Security

[Spring Security][회원가입 및 로그인 예제 8/9] View 구현

들어가며...

앞 글에서 Controller까지 구현하였으므로 설정 부분을 제외하고 Back End 부분은 끝난 상태입니다. 이번 글에서는 Front End 코드만 대략 살펴볼 것입니다. 사용된 기술은 Thymeleaf, Bootstrap 정도입니다.

Bootstrap에 대한 설명은 홈페이지의 도큐먼트가 워낙 잘 나와 있으니 아래 링크를 참조하시면 될 듯 합니다.

 

https://getbootstrap.com/docs/4.4/getting-started/introduction/

 

Introduction

Get started with Bootstrap, the world’s most popular framework for building responsive, mobile-first sites, with BootstrapCDN and a template starter page.

getbootstrap.com

Thymeleaf는 JSP와 같이 Web Template Engine 중 Text Template Engine의 한 종류입니다. 이 또한 이번글에서는 설명을 생략합니다. 

https://www.thymeleaf.org/

 

Thymeleaf

Integrations galore Eclipse, IntelliJ IDEA, Spring, Play, even the up-and-coming Model-View-Controller API for Java EE 8. Write Thymeleaf in your favourite tools, using your favourite web-development framework. Check out our Ecosystem to see more integrati

www.thymeleaf.org

본 프로젝트의 크게 7개의 화면으로 구성되어 있습니다. 각 화면의 구성은 1회차 글을 참조하시기 바랍니다.

2020/03/13 - [Programming/Spring Security] - [Spring Security][회원가입 및 로그인 예제 1/9] Spring Security 및 프로젝트 개요

 

[Spring Security][회원가입 및 로그인 예제 1/9] Spring Security 및 프로젝트 개요

들어가며... Spring Security를 사용하여 간단한 로그인 및 회원가입 어플리케이션 구현을 진행해 보려 합니다. 전체 어플리케이션의 내용은 Spring Security의 내용 보다 다른 기술에 대한 내용이 많아질 듯 하..

u2ful.tistory.com

 

  • Table of Contents
    • HTML, CSS and Javascript(jQuery)

HTML, CSS and Javascript(jQuery)

위에서도 언급하였듯이 View 단은 코드에 대한 별도의 설명은 안하고 필요할 경우 화면의 흐름정도만 설명하겠습니다.


● 로그인

● login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Security Tutorial</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/login.css" th:href="@{/css/login.css}"/>
</head>

<body>
    <div class="container-fluid p-5 mt-5 text-center">
        <h1 class="display-4 text-light">Spring Security</h1>
        <form action="/registration.html" th:action="@{/registration}" method="get">
            <button class="btn btn-sm btn-warning text-uppercase my-4" type="Submit">Go To Sign Up</button>
        </form>

        <div class="row">
            <div class="col-md-3 col-xl-4"></div>
            <div class="col-md-6 col-xl-4">
                <div class="card login-form border-0">
                    <i class="fas fa-key mt-4 mx-auto fa-3x text-success"></i>
                    <div class="card-body">
                        <form th:action="@{/login}" method="POST" class="form-signin">
                            <h3 class="text-uppercase mb-5 text-light">Welcome</h3>
                            <input type="text" id="username" name="username" placeholder="User name" class="form-control my-3 login-text" autofocus />
                            <input type="password" placeholder="Password" id="password" name="password" class="form-control mb-3 login-text"/>
                    
                            <div th:if="${param.error}">
                                <p class="error-message" th:text="${errorMessage}">User Name or Password invalid, please verify</p>
                            </div>
                            <button class="btn btn-lg btn-success btn-block text-uppercase" name="Submit" value="Login" type="Submit" th:text="Login">Sign In</button>
                        </form>
                    </div>
                </div>
            </div>
            <div class="col-md-3 col-xl-4"></div>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

인증되지 않은 사용자가 "localhost:8080"를 포함 임의의 파일 패스로 접속 시 최초로 로그인 화면으로 이동하게 됩니다. 아래 왼편의 화면이 나오면 정상이며 등록되지 않은 아이디 패스워드로 로그인하려 할 경우 오른편 화면이 나오면 정상입니다.

 

로그인(좌), 로그인 실패(우)

● login.css

body {
    background: #043041;
    height: 100vh;
}

.login-form {
    background: #043041;
}

.error-message {
    color: red;
}

.login-text {
    background: #1F4758;
    color: #eee;
    border: 0;
}

.login-text:focus {
	color: #111;
}

● 사용자 등록

로그인 정보가 없을 경우 "GO TO SIGN UP" 버튼을 클릭하여 사용자 등록 화면으로 이동하여 사용자 등록을 수행합니다. 이전 코드에서도 설명하였듯이 사용자명을 "admin" => ADMIN 권한, "user" => MANAGER 권한 그 외의 사용자명일 경우 "GUEST" 권한을 할당하게 해놓았습니다. 이전 코드를 잠시 살펴 보도록 하겠습니다.

/**
 * Save the user information
 */
@Override
@Transactional
public Account setUser(Account user) throws Exception {
	//< encoding the password
	user.setPassword(bcryptPasswordEncoder.encode(user.getPassword()));
	//< set the active flag
	user.setIsActive(true);
	//< set the user role
	Role userRole = null;
	if(user.getUsername().equals("admin")) {
		userRole = roleRepository.findByRole(ERole.ADMIN.getValue());
	}
	else if(user.getUsername().equals("user")) {
		userRole = roleRepository.findByRole(ERole.MANAGER.getValue());
	}
	else {
		userRole = roleRepository.findByRole(ERole.GUEST.getValue());
	}
	
	//< set the user roles
	user.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
	
	//< save the user information and return result
	return accountRepository.save(user);
}

 

● registration.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Registration Form</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/registration.css" th:href="@{/css/registration.css}"/>
</head>
<body>
    <div class="container-fluid p-5 mt-5 text-center">
        <h1 class="display-4 text-light">Spring Security</h1>
        <form action="/login.html" th:action="@{/}" method="get">
            <button class="btn btn-sm btn-success text-uppercase my-4" type="Submit">Go To Sign In</button>
        </form>
        
        <div class="row">
            <div class="col-md-3 col-xl-4"></div>
            <div class="col-md-6 col-xl-4">
                <div class="card signup-form border-0">
                    <i class="fas fa-sign-in-alt mt-4 mx-auto fa-3x text-warning"></i>
                    <div class="card-body">
                        <form autocomplete="off" action="#" th:action="@{/registration}" th:object="${account}" method="post" class="form-horizontal" role="form">
                            <h3 class="text-white text-uppercase mb-5">Registration</h3>
                            <!-- Email -->
                            <div class="form-group">
                                <input type="text" th:field="*{email}" placeholder="Email" class="form-control signup-text" autofocus />
                                <label th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="validation-message"></label>
                            </div>
                            <!-- user name -->
                            <div class="form-group">
                                <input type="text" th:field="*{username}" placeholder="User Name" class="form-control signup-text"/> 
                                <label th:if="${#fields.hasErrors('username')}" th:errors="*{username}" class="validation-message"></label>
                            </div>
                            <!-- password -->
                            <div class="form-group">
                                <input type="password" th:field="*{password}" placeholder="Password" class="form-control signup-text"/>
                                <label th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="validation-message"></label>
                            </div>
                            <!-- confirm password -->
                            <div class="form-group">
                                <input type="password" th:field="*{confirmPassword}" placeholder="Confirm Password" class="form-control signup-text"/> 
                                <label th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}" class="validation-message"></label>
                            </div>
                            <!-- submit button -->
                            <div class="form-group">
                                <button type="submit" class="btn btn-warning btn-block text-uppercase">sign up</button>
                            </div>
                            
                            <h4><span class="text-success" th:utext="${successMessage}">User has been registered successfully</span></h4>
                        </form>
                    </div>
                </div>
            </div>
            <div class="col-md-3 col-xl-4"></div>
        </div>
    </div>

<!-- Javascript of Bootstrap  -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

아래는 사용자 등록 화면과 사용자 등록 시 validation 체크 시 실패한 화면 입니다.

 

사용자 등록(좌), Validation 실패(우)

 

● registration.css

body {
    background: #043041;
    height: 100vh;
}

.signup-form {
    background: #043041;
}

.signup-text {
    background: #1F4758;
    color: #eee;
    border: 0;
}

.signup-text:focus {
	color: #111;
}

.validation-message {
	color: #ee4835;
	margin-bottom: auto;
}

● 홈화면

사용자 등록이 완료한 후 로그인 페이지로 이동 후 로그인을 수행하면 최초 접속 화면을 볼 수 있습니다.

 

● index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home Page</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/home.css" th:href="@{/css/home.css}"/>
</head>
<body>
    <div class="container-fluid p-5 mt-5">
        <div class="text-light text-center my-5">
            <h1 class="display-4 mb-4 text-uppercase">Welcome, <span th:text="${username}" class="text-success">Leo</span></h1>
            <form th:action="@{/logout}" method="get">
                <button class="btn btn-lg btn-info" name="registration" type="Submit">Logout</button>
            </form>    
        </div>

        <div class="row mx-5">
            <div class="col-md-4">
                <div class="card">
                    <i class="fas fa-users-cog fa-7x mx-auto my-5 text-danger"></i>
                    <div class="card-body text-center">
                        <h3 class="card-title text-danger mb-4">Administrator</h3>
                        	<form action="/admin.html" th:action="@{/home/admin}" method="get">
							<button class="btn btn-md btn-block btn-danger">Go</button>
                        	</form>
                    </div>
                </div>
            </div>
            <div class="col-md-4">
                <div class="card">
                    <i class="fas fa-user-friends fa-7x mx-auto my-5 text-success"></i>
                    <div class="card-body text-center">
                        <h3 class="card-title text-success mb-4">User</h3>
                        	<form action="/user.html" th:action="@{/home/user}" method="get">
							<button class="btn btn-md btn-block btn-success">Go</button>
                        	</form>                        
                    </div>
                </div>
            </div>
            <div class="col-md-4">
                <div class="card">
                    <i class="fas fa-user-secret fa-7x mx-auto my-5 text-warning"></i>
                    <div class="card-body text-center">
                        <h3 class="card-title text-warning mb-4">Guest</h3>
                        	<form action="/guest.html" th:action="@{/home/guest}" method="get">
							<button class="btn btn-md btn-block btn-warning">Go</button>
                        	</form>                        
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

 

 

● home.css

body {
    background: #073040;
    height: 100vh;
}

.card {
    background: #214757;
    border: 1px solid #535353;
}

 


● 사용자별 화면 및 에러

현재 정의한 3가지 종류의 권한과 해당 페이지로 이동할 수 있는 메뉴가 존재하며 로그인한 권한의 페이지로 이동하면 정상적인 화면으로 이동되나 그렇지 않을 경우는 권한 없음의 에러 화면이 출력되게 됩니다.

아래는 3가지 권한 및 HTTP error에 대한 HTML과 성공 실패에 대한 화면입니다.

 

● admin.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Page</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/common.css" th:href="@{/css/common.css}"/>
</head>
<body>
    <div class="container-fluid">
        <div class="pt-5 mt-5 text-center">
            <i class="fas fa-users-cog fa-7x my-5 text-danger"></i>
            <form action="/home.html" th:action="@{/home}">
                <button class="btn btn-lg btn-info mb-5">Home</button>
            </form>
            <h4 class="text-light">Content Available Only <span class="text-danger">Admin</span> Role</h4>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

 

 

● user.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Page</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/common.css" th:href="@{/css/common.css}"/>
</head>
<body>
    <div class="container-fluid">
        <div class="pt-5 mt-5 text-center">
            <i class="fas fa-user-friends fa-7x my-5 text-success"></i>
            <form action="/home.html" th:action="@{/home}">
                <button class="btn btn-lg btn-info mb-5">Home</button>
            </form>
            <h4 class="text-light">Content Available Only <span class="text-success">User</span> Role</h4>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

 

 

● guest.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Page</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/common.css" th:href="@{/css/common.css}"/>
</head>
<body>
    <div class="container-fluid">
        <div class="pt-5 mt-5 text-center">
            <i class="fas fa-user-secret fa-7x my-5 text-warning"></i>
            <form action="/home.html" th:action="@{/home}">
                <button class="btn btn-lg btn-info mb-5">Home</button>
            </form>
            <h4 class="text-light">Content Available Only <span class="text-warning">Guest</span> Role</h4>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
</body>
</html>

 

 

● error.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>404 Page</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/common.css" th:href="@{/css/common.css}"/>
</head>
<body>
    <div class="container-fluid">
        <div class="pt-5 mt-5 text-center">
        	<div th:switch="${errorCode}">
				<i th:case="'404'" class="fas fa-times-circle fa-7x my-5 text-danger"></i>
				<i th:case="'403'" class="fas fa-hand-paper fa-7x my-5 text-danger"></i>
				<i th:case="*" class="fas fa-bomb fa-7x my-5 text-danger"></i>
        	</div>
            <h1 class="display-2 text-danger" th:text="${errorCode}">Error Occurred!!</h1>
            <h5 class="text-light mb-5" th:text="${errorMessage}">An error has occurred. Please contact the administrator</h5>
			<button id="error-back" class="btn btn-lg btn-info mb-5">Back</button>
        </div>
    </div>

    <!-- Javascript of Bootstrap  -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script src="/lib/fontawesome-free-5.12.1-web/js/all.js" crossorigin="anonymous"></script>
    <script src="/js/common.js"></script>
</body>
</html>

 

 

● common.css

body {
    background: #043041;
    height: 100vh;
}

 

 

● common.js

/**
 * History back
 */
$("#error-back").on("click", function() {
	window.history.back();
});
 

 

권한 있는 페이지로 이동(좌), 권한 없는 페이지로 이동(우)

마무리...

이상으로 Spring Security의 인증 및 권한 부분에 초점을 맞춘 UI라서 html, css의 내용은 크게 어렵지 않으리라 판단됩니다.

 

 


U2ful은 입니다. @U2ful Corp.