Skip to content

Commit

Permalink
feat: 로그인시 세션에 사용자 저장 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
greeng00se committed Sep 2, 2023
1 parent 92046ec commit f73d0b7
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 106 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
- [x] QueryString 파싱 기능을 추가한다.
- [x] 로그인 기능(/login)을 구현한다.
- [x] 로그인의 성공하면 http status 302를 반환한다.
- [x] 로그인에 성공하면 세션에 사용자를 저장한다.
- [x] 로그인에 성공하면 JSESSIONID를 Set-Cookie 헤더에 담아 보낸다.
- [x] 로그인에 성공한 상태에서 로그인 페이지로 접근하면 index.html로 리다이렉트한다.
- [x] location header에 리다이렉트할 url을 추가한다.
- [x] 로그인에 실패하는 경우 401.html로 리다리엑트한다.
- [ ] 회원가입 기능(/register)을 구현한다.
- [ ] 회원가입 페이지의 경우 GET을 사용하여 보여준다.
- [ ] 회원가입의 경우 POST를 사용한다.
- [ ] 회원가입을 완료하는 경우 index.html로 리다이렉트한다.
- [x] 로그인에 실패하는 경우 401.html로 리다이렉트한다.
- [x] 회원가입 기능(/register)을 구현한다.
- [x] 회원가입 페이지의 경우 GET을 사용하여 보여준다.
- [x] 회원가입의 경우 POST를 사용한다.
- [x] 회원가입을 완료하는 경우 index.html로 리다이렉트한다.

40 changes: 30 additions & 10 deletions tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import nextstep.jwp.exception.UncheckedServletException;
import nextstep.jwp.model.User;
import org.apache.coyote.Processor;
import org.apache.coyote.http11.common.HttpCookie;
import org.apache.coyote.http11.common.HttpMethod;
import org.apache.coyote.http11.common.HttpStatus;
import org.apache.coyote.http11.common.Session;
import org.apache.coyote.http11.common.SessionManager;
import org.apache.coyote.http11.request.RequestBody;
import org.apache.coyote.http11.request.RequestHeader;
Expand All @@ -27,6 +29,9 @@
public class Http11Processor implements Runnable, Processor {

private static final Logger LOG = LoggerFactory.getLogger(Http11Processor.class);
private static final String INDEX_PAGE = "/index.html";
private static final String REGISTER_PAGE = "/register.html";
private static final String LOGIN_PAGE = "/login.html";

private final Socket connection;
private final HttpResponseGenerator httpResponseGenerator = new HttpResponseGenerator();
Expand Down Expand Up @@ -93,33 +98,48 @@ private ResponseEntity handleRequest(
LOG.info("request uri: {}", requestLine.getUri());
final String path = requestLine.parseUriWithOutQueryString();
if (path.equals("/login")) {
return login(requestLine, requestBody);
return login(requestLine, requestHeader, requestBody);
}
if (path.equals("/register")) {
return register(requestLine, requestBody);
}
return new ResponseEntity(HttpStatus.OK, path);
}

private ResponseEntity login(final RequestLine requestLine, final RequestBody requestBody) {
private ResponseEntity login(
final RequestLine requestLine,
final RequestHeader requestHeader,
final RequestBody requestBody
) {
if (requestLine.getHttpMethod() == HttpMethod.GET) {
return new ResponseEntity(HttpStatus.OK, "/login.html");
final HttpCookie httpCookie = requestHeader.parseCookie();
final Session session = sessionManager.findSession(httpCookie.get("JSESSIONID"));
if (session != null) {
return new ResponseEntity(HttpStatus.FOUND, INDEX_PAGE);
}
return new ResponseEntity(HttpStatus.OK, LOGIN_PAGE);
}
final String account = requestBody.get("account");
final String password = requestBody.get("password");
return InMemoryUserRepository.findByAccount(account)
.filter(user -> user.checkPassword(password))
.map(user -> {
final ResponseEntity responseEntity = new ResponseEntity(HttpStatus.FOUND, "/index.html");
responseEntity.setCookie("JSESSIONID", UUID.randomUUID().toString());
return responseEntity;
})
.map(this::loginSuccess)
.orElseGet(() -> new ResponseEntity(HttpStatus.UNAUTHORIZED, "/401.html"));
}

private ResponseEntity loginSuccess(final User user) {
final String uuid = UUID.randomUUID().toString();
final ResponseEntity responseEntity = new ResponseEntity(HttpStatus.FOUND, INDEX_PAGE);
responseEntity.setCookie("JSESSIONID", uuid);
final Session session = new Session(uuid);
session.setAttribute("user", user);
sessionManager.add(session);
return responseEntity;
}

private ResponseEntity register(final RequestLine requestLine, final RequestBody requestBody) {
if (requestLine.getHttpMethod() == HttpMethod.GET) {
return new ResponseEntity(HttpStatus.OK, "/register.html");
return new ResponseEntity(HttpStatus.OK, REGISTER_PAGE);
}
final String account = requestBody.get("account");

Expand All @@ -130,6 +150,6 @@ private ResponseEntity register(final RequestLine requestLine, final RequestBody
final String password = requestBody.get("password");
final String email = requestBody.get("email");
InMemoryUserRepository.save(new User(account, password, email));
return new ResponseEntity(HttpStatus.FOUND, "/index.html");
return new ResponseEntity(HttpStatus.FOUND, INDEX_PAGE);
}
}
192 changes: 101 additions & 91 deletions tomcat/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
@@ -1,106 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>대시보드</title>
<link href="css/styles.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/js/all.min.js" crossorigin="anonymous"></script>
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<!-- Navbar Brand-->
<a class="navbar-brand ps-3" href="index.html">대시보드</a>
<!-- Sidebar Toggle-->
<button class="btn btn-link btn-sm order-1 order-lg-0 me-4 me-lg-0" id="sidebarToggle" href="#!"><i class="fas fa-bars"></i></button>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title>대시보드</title>
<link href="css/styles.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/js/all.min.js"
crossorigin="anonymous"></script>
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<!-- Navbar Brand-->
<a class="navbar-brand ps-3" href="index.html">대시보드</a>
<!-- Sidebar Toggle-->
<button class="btn btn-link btn-sm order-1 order-lg-0 me-4 me-lg-0" id="sidebarToggle" href="#!"><i
class="fas fa-bars"></i></button>

<!-- before login -->
<div class="navbar-nav d-none d-md-inline-block ms-auto me-0 me-md-3 my-2 my-md-0">
<a class="nav-link" href="login" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
</div>
<!-- before login -->
<!-- before login -->
<div class="navbar-nav d-none d-md-inline-block ms-auto me-0 me-md-3 my-2 my-md-0">
<a class="nav-link" href="login" role="button"><i class="fas fa-user fa-fw"></i>&nbsp;로그인</a>
</div>
<!-- before login -->

<!-- after login -->
<!-- <ul class="navbar-nav ms-auto ms-md-0 me-3 me-lg-4">-->
<!-- <li class="nav-item dropdown">-->
<!-- <a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fas fa-user fa-fw"></i></a>-->
<!-- <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">-->
<!-- <li><a class="dropdown-item" href="#!">Settings</a></li>-->
<!-- <li><hr class="dropdown-divider" /></li>-->
<!-- <li><a class="dropdown-item" href="#!">Logout</a></li>-->
<!-- </ul>-->
<!-- </li>-->
<!-- </ul>-->
<!-- after login -->
<!-- after login -->
<ul class="navbar-nav ms-auto ms-md-0 me-3 me-lg-4">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false"><i class="fas fa-user fa-fw"></i></a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#!">Settings</a></li>
<li>
<hr class="dropdown-divider"/>
</li>
<li><a class="dropdown-item" href="#!">Logout</a></li>
</ul>
</li>
</ul>
<!-- after login -->

</nav>
<div id="layoutSidenav">
<div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu">
<div class="nav">
<div class="sb-sidenav-menu-heading">Core</div>
<a class="nav-link" href="index.html">
<div class="sb-nav-link-icon"><i class="fas fa-tachometer-alt"></i></div>
대시보드
</a>
</div>
</div>
</nav>
</nav>
<div id="layoutSidenav">
<div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu">
<div class="nav">
<div class="sb-sidenav-menu-heading">Core</div>
<a class="nav-link" href="index.html">
<div class="sb-nav-link-icon"><i class="fas fa-tachometer-alt"></i></div>
대시보드
</a>
</div>
</div>
<div id="layoutSidenav_content">
<main>
<div class="container-fluid px-4">
<h1 class="mt-4">대시보드</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item active">첫 페이지</li>
</ol>
<div class="row">
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-bar me-1"></i>
Bar Chart
</div>
<div class="card-body"><canvas id="myBarChart" width="100%" height="50"></canvas></div>
</div>
</nav>
</div>
<div id="layoutSidenav_content">
<main>
<div class="container-fluid px-4">
<h1 class="mt-4">대시보드</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item active">첫 페이지</li>
</ol>
<div class="row">
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-bar me-1"></i>
Bar Chart
</div>
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-pie me-1"></i>
Pie Chart
</div>
<div class="card-body"><canvas id="myPieChart" width="100%" height="50"></canvas></div>
</div>
<div class="card-body">
<canvas id="myBarChart" width="100%" height="50"></canvas>
</div>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container-fluid px-4">
<div class="d-flex align-items-center justify-content-between small">
<div class="text-muted">Copyright &copy; Your Website 2021</div>
<div>
<a href="index.html">Home</a>
&middot;
<a href="#">Privacy Policy</a>
&middot;
<a href="#">Terms &amp; Conditions</a>
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-pie me-1"></i>
Pie Chart
</div>
<div class="card-body">
<canvas id="myPieChart" width="100%" height="50"></canvas>
</div>
</div>
</div>
</footer>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container-fluid px-4">
<div class="d-flex align-items-center justify-content-between small">
<div class="text-muted">Copyright &copy; Your Website 2021</div>
<div>
<a href="index.html">Home</a>
&middot;
<a href="#">Privacy Policy</a>
&middot;
<a href="#">Terms &amp; Conditions</a>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="assets/chart-area.js"></script>
<script src="assets/chart-bar.js"></script>
<script src="assets/chart-pie.js"></script>
</body>
</footer>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="assets/chart-area.js"></script>
<script src="assets/chart-bar.js"></script>
<script src="assets/chart-pie.js"></script>
</body>
</html>

0 comments on commit f73d0b7

Please sign in to comment.