이 예제에는 스프링 시큐리티Thymeleaf가 사용되었습니다.

기초적인 데이터베이스 insert 예제로, 특별한 내용은 없고 다음을 연습하기 위해 만들었습니다.

  • 회원 테이블에 비밀번호를 BCrypt로 해싱한 텍스트를 입력
  • 원칙적으로 입력한 값에 대한 유효성 검사는 프론트엔드 측과 백엔드 측 모두에서 행해져야 하는데, 백엔드 측의 유효성 검사 과정을 추가

시간 관계상 프론트엔드 측 유효성 검사는 구현하지 않았습니다.

@GetMapping@PostMapping은 기존의 @RequestMapping 을 GET 방식 또는 POST 방식으로 지정할 수 있습니다. @PostMapping("/url")은 @RequestMapping(value="/url", method=RequestMethod.POST)과 동일한 기능을 합니다.

 


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta charset="UTF-8">
<title>회원가입</title>
<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/4.4.1/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" href="/board.css">
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<img class="d-block mx-auto mb-4" src="https://getbootstrap.com/docs/4.0/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
<h2>회원가입 결과 여부</h2>
<pre th:text="${resultMsg}"></pre>
<p>
<a href="" th:unless="${isSuccess}">회원가입 다시하기</a>
<a href="/" th:if="${isSuccess}">홈페이지로 돌아가기</a>
</p>
</div>
</div>
</body>
</html>


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta charset="UTF-8">
<title>회원가입</title>
<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/4.4.1/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" href="/board.css">
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<img class="d-block mx-auto mb-4" src="https://getbootstrap.com/docs/4.0/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
<h2>회원가입</h2>
<p class="lead">회원가입하세요. 가입하면 게시판을 열람할 수 있습니다.</p>
</div>
<div class="col-md-12 order-md-1">
<h4 class="mb-3">회원정보</h4>
<form class="needs-validation" novalidate th:action="@{/signup}" method="POST">
<div class="mb-3">
<label for="username">아이디 (username)</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@</span>
</div>
<input type="text" class="form-control" id="username" placeholder="Username" required name="user-id">
<div class="invalid-feedback" style="width: 100%;">Your username is required.</div>
</div>
</div>
<div class="mb-3">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" placeholder="" value="" required name="user-password">
<div class="invalid-feedback">유효한 비밀번호가 필요합니다.</div>
</div>
<div class="mb-3">
<label for="firstName">이름</label>
<input type="text" class="form-control" id="real-name" placeholder="" value="" required name="user-real-name">
<div class="invalid-feedback">유효한 이름을 입력해야합니다.</div>
</div>
<div class="mb-3">
<label for="email">이메일</label>
<input type="email" class="form-control" id="email" placeholder="you@example.com" name="user-email">
<div class="invalid-feedback">올바른 이메일을 입력하세요.</div>
</div>
<div class="mb-3">
<label for="address">좋아하는 음식</label> <input type="text" class="form-control" id="food" placeholder="예) 치킨" required name="user-food">
<div class="invalid-feedback">좋아하는 음식을 입력하세요.</div>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit">가입하기</button>
<hr class="mb-4">
<footer th:replace="/fragments/semantic :: footer"></footer>
</form>
</div>
</div>
</body>
</html>

view raw

signup.html

hosted with ❤ by GitHub


package com.springboot.security.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class SimpleUserDAO {
@Autowired JdbcTemplate jt;
public List<Map<String, ?>> getUserInfo(String username) {
return jt.query("select * from simple_users where username=?", new Object[] {username} , (rs, rowNum) -> {
Map<String, Object> anUser = new HashMap<>();
anUser.put("username", rs.getString(2));
anUser.put("password", rs.getString(3));
anUser.put("role", rs.getString(4));
anUser.put("food", rs.getString(5));
return anUser;
});
}
public int insertUserInfo(Map<String, String> user) {
String sql = "insert into "
+ "simple_users(iduser, username, password, role, food, email, real_name) "
+ "values(0, ?, ?, 'GUEST', ?, ?, ?)";
return jt.update(sql,
user.get("user-id"),
user.get("user-password"),
user.get("user-food"),
user.get("user-email"),
user.get("user-real-name")
);
}
}


package com.springboot.security.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.springboot.security.dao.SimpleUserDAO;
@Controller
public class UserController {
@Autowired SimpleUserDAO sud;
@GetMapping("/signup")
public String signUp(Model model) {
return "signup/signup";
}
@PostMapping("/signup")
public String signUpProc(Model model, @RequestParam Map<String, String> params) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
System.out.println(params);
String userId = params.get("user-id");
String userPwd = params.get("user-password");
String userRealName = params.get("user-real-name");
String userFood = params.get("user-food");
// back-end validation
String result = "";
boolean isAllValidate = true;
if(userId.length() < 4) {
result += "user-id must be at least 4 character long.\n";
isAllValidate = false;
}
if(userPwd.length() < 4) {
result += "user-password must be at least 4 character long.\n";
isAllValidate = false;
}
if(userRealName.length() <= 0) {
result += "user-name is not entered.\n";
isAllValidate = false;
}
if(userFood.length() <= 0) {
result += "user-food is not entered.\n";
isAllValidate = false;
}
// submit to database
if(isAllValidate) {
params.remove("_csrf");
params.put("user-password", passwordEncoder.encode(userPwd));
try {
int insertResult = sud.insertUserInfo(params);
if(insertResult >= 1) {
result += "You have successfully registered.";
} else {
result += "Sign-up failed. There may be duplicate information or other issues.";
isAllValidate = false;
}
} catch(Exception e) {
e.printStackTrace();
result += "Sign-up failed. There may be duplicate information or other issues.";
isAllValidate = false;
}
}
model.addAttribute("isSuccess", isAllValidate);
model.addAttribute("resultMsg", result);
return "signup/signup-result";
}
}

 

기존에 존재하는 아이디로 회원가입을 시도

기존에 존재하는 아이디로 회원가입을 시도 결과

 

유효하지 않은 입력 정보로 가입 시도

유효하지 않은 입력 정보로 가입 시도 결과

 

정상적인 입력 정보로 회원 가입 시도

정상적인 입력 정보로 회원 가입 결과

 

입력 정보 확인

 

로그인 후 게시판(Spring Boot 예제: 초간단 게시판)에 글 작성

문의 | 코멘트 또는 yoonbumtae@gmail.com




0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다