SpringBoot3

[SpringSecurity-03] 스프링 시큐리티 - CRUD

HJ922 2024. 11. 27. 00:00

[SpringSecurity-02] 스프링 시큐리티 - 활용

 

[SpringSecurity-02] 스프링 시큐리티 - 활용

[SpringSecurity-01] 스프링 시큐리티 - 이해 [SpringSecurity-01] 스프링 시큐리티 - 이해SpringFramework에서 REST API를 사용하는 백엔드 개발자 지망생이라면한번쯤 회원과 관련된 인증/인가를 구현해야겠다

hjustin.tistory.com

 

 

이번에는 지난번에 말했던 CRUD 즉 회원가입,로그인,로그아웃을 구현해볼거에요!

 

Security에서 DB에 멤버정보가 없다면 회원가입을 진행하고

멤버정보가 있다면 로그인을하는 형식으로 구성됩니다.

resources 디렉토리 구조

 

그전에 resources의 디렉토리구조에 대해서 알아야합니다!

static : 정적인 파일이 들어갑니다. image, css , javascript 등 ..

templates : HTML 파일이 들어갑니다!

 

따라서 만약 웹서버를 따로 만들지않는다면 templates폴더에 html파일을 만들고 static에있는 이미지, javascript, css를 불러와서 사용하는 형식이 됩니다.

 

build.gradle 의존성에 thymeleaf를 추가해줍시다. -> html에서 jsp 처럼 자바문법을 사용할 수 있음

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

 

 

 

 

 

먼저 회원가입, 로그인을 담당할 컨트롤러를 만들어야합니다. 

UserViewController
UserViewController

 

 

templates 폴더 구조

login과 signup HTML 코드는 다음과 같습니다!

 

<login.html>

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>로그인</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">

    <style>
        .gradient-custom {
            background: linear-gradient(to right, rgba(106, 17, 203, 1), rgba(37, 117, 252, 1))
        }
    </style>
</head>
<body class="gradient-custom">
<section class="d-flex vh-100">
    <div class="container-fluid row justify-content-center align-content-center">
        <div class="card bg-dark" style="border-radius: 1rem;">
            <div class="card-body p-5 text-center">
                <h2 class="text-white">LOGIN</h2>
                <p class="text-white-50 mt-2 mb-5">서비스를 사용하려면 로그인을 해주세요!</p>

                <div class = "mb-2">
                    <form action="/login" method="POST">
                        <input type="hidden" th:name="${_csrf?.parameterName}" th:value="${_csrf?.token}" />
                        <div class="mb-3">
                            <label class="form-label text-white">Email address</label>
                            <input type="email" class="form-control" name="username">
                        </div>
                        <div class="mb-3">
                            <label class="form-label text-white">Password</label>
                            <input type="password" class="form-control" name="password">
                        </div>
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </form>

                    <button type="button" class="btn btn-secondary mt-3" onclick="location.href='/signup'">회원가입</button>
                </div>
            </div>
        </div>
    </div>
</section>
</body>
</html>

<signup.html>

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>회원 가입</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">

  <style>
    .gradient-custom {
      background: linear-gradient(to right, rgba(254, 238, 229, 1), rgba(229, 193, 197, 1))
    }
  </style>
</head>
<body class="gradient-custom">
<section class="d-flex vh-100">
  <div class="container-fluid row justify-content-center align-content-center">
    <div class="card bg-dark" style="border-radius: 1rem;">
      <div class="card-body p-5 text-center">
        <h2 class="text-white">SIGN UP</h2>
        <p class="text-white-50 mt-2 mb-5">서비스 사용을 위한 회원 가입</p>

        <div class = "mb-2">
          <form th:action="@{/user}" method="POST">
            <!-- 토큰을 추가하여 CSRF 공격 방지 -->
            <input type="hidden" th:name="${_csrf?.parameterName}" th:value="${_csrf?.token}" />
            <div class="mb-3">
              <label class="form-label text-white">Email address</label>
              <input type="email" class="form-control" name="email">
            </div>
            <div class="mb-3">
              <label class="form-label text-white">Password</label>
              <input type="password" class="form-control" name="password">
            </div>

            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
        </div>
      </div>
    </div>
  </div>
</section>
</body>
</html>

 

이제 로그인과 회원가입을 만들었으니 로그아웃을 만들어야 합니다.

UserViewController에 다음과같이 Api를 추가해줍니다.

logout Api

위의 동작은 로그아웃할때 SecurityContext에 혹시나 남아있을수 있는 인증정보를 파기하는 내용입니다.

article Api(메인페이지)

 

 

정리하자면 다음과같이 동작하게된다

 

http 요청 -> Security에서 인증되지않은 사용자는 LoginForm페이지로 보냄 -> login페이지에서 아이디 패스워드 입력 -> 서버에서 인증 로직 동작 (DB에서 찾아서 같은지 비교) -> 같다면 메인페이지 -> 로그아웃

 

login page
main page