From 5956b9fef5c6c15581d0696e1d28e8fc7f91d3b7 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 22:37:46 +0900 Subject: [PATCH 01/26] =?UTF-8?q?feat:=20Auth=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/auth/AuthService.java | 17 +++++ .../java/roomescape/auth/LoginResponse.java | 20 ++++++ .../roomescape/auth/TokenLoginController.java | 68 +++++++++++++++++++ .../java/roomescape/auth/TokenRequest.java | 30 ++++++++ .../java/roomescape/auth/TokenResponse.java | 20 ++++++ .../roomescape/member/MemberController.java | 13 ++-- src/test/java/roomescape/MissionStepTest.java | 12 ++++ 7 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 src/main/java/roomescape/auth/AuthService.java create mode 100644 src/main/java/roomescape/auth/LoginResponse.java create mode 100644 src/main/java/roomescape/auth/TokenLoginController.java create mode 100644 src/main/java/roomescape/auth/TokenRequest.java create mode 100644 src/main/java/roomescape/auth/TokenResponse.java diff --git a/src/main/java/roomescape/auth/AuthService.java b/src/main/java/roomescape/auth/AuthService.java new file mode 100644 index 00000000..6114305c --- /dev/null +++ b/src/main/java/roomescape/auth/AuthService.java @@ -0,0 +1,17 @@ +package roomescape.auth; + +import org.springframework.stereotype.Service; +import roomescape.member.MemberResponse; + +@Service +public class AuthService { + public TokenResponse createToken(TokenRequest tokenRequest) { + + String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwibmFtZSI6ImFkbWluIiwicm9sZSI6IkFETUlOIn0.cwnHsltFeEtOzMHs2Q5-ItawgvBZ140OyWecppNlLoI"; + return new TokenResponse(token); + } + + public LoginResponse findUserByToken(String token) { + return new LoginResponse("어드민"); + } +} diff --git a/src/main/java/roomescape/auth/LoginResponse.java b/src/main/java/roomescape/auth/LoginResponse.java new file mode 100644 index 00000000..5f610da5 --- /dev/null +++ b/src/main/java/roomescape/auth/LoginResponse.java @@ -0,0 +1,20 @@ +package roomescape.auth; + +public class LoginResponse { + private String name; + + public LoginResponse() { + } + + public LoginResponse(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/roomescape/auth/TokenLoginController.java b/src/main/java/roomescape/auth/TokenLoginController.java new file mode 100644 index 00000000..4dc0648a --- /dev/null +++ b/src/main/java/roomescape/auth/TokenLoginController.java @@ -0,0 +1,68 @@ +package roomescape.auth; + + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TokenLoginController { + private final AuthService authService; + + public TokenLoginController(AuthService authService) { + this.authService = authService; + } + + @PostMapping("/login") + public ResponseEntity login(@RequestBody TokenRequest tokenRequest, HttpServletResponse response) { + TokenResponse tokenResponse = authService.createToken(tokenRequest); + + response.addCookie(createHttpOnlyCookie("token", tokenResponse.getAccessToken())); + + return ResponseEntity.ok().build(); + } + + private Cookie createHttpOnlyCookie(String name, String value) { + Cookie cookie = new Cookie(name, value); + cookie.setPath("/"); + cookie.setHttpOnly(true); + return cookie; + } + + @PostMapping("/logout") + public ResponseEntity logout(HttpServletResponse response) { + Cookie cookie = new Cookie("token", ""); + cookie.setHttpOnly(true); + cookie.setPath("/"); + cookie.setMaxAge(0); + response.addCookie(cookie); + return ResponseEntity.ok().build(); + } + + @GetMapping("/login/check") + public ResponseEntity checkLogin(HttpServletRequest request) { + String token = null; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("token".equals(cookie.getName())) { + token = cookie.getValue(); + break; + } + } + } + + if (token == null) { + return ResponseEntity.status(401).build(); + } + + LoginResponse loginResponse = authService.findUserByToken(token); + + return ResponseEntity.ok(loginResponse); + } +} diff --git a/src/main/java/roomescape/auth/TokenRequest.java b/src/main/java/roomescape/auth/TokenRequest.java new file mode 100644 index 00000000..e955435a --- /dev/null +++ b/src/main/java/roomescape/auth/TokenRequest.java @@ -0,0 +1,30 @@ +package roomescape.auth; + +public class TokenRequest { + private String email; + private String password; + + public TokenRequest() { + } + + public TokenRequest(String email, String password) { + this.email = email; + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/roomescape/auth/TokenResponse.java b/src/main/java/roomescape/auth/TokenResponse.java new file mode 100644 index 00000000..26020fcd --- /dev/null +++ b/src/main/java/roomescape/auth/TokenResponse.java @@ -0,0 +1,20 @@ +package roomescape.auth; + +public class TokenResponse { + private String accessToken; + + public TokenResponse() { + } + + public TokenResponse(String accessToken) { + this.accessToken = accessToken; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } +} diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index 881ae5e0..d0b823c6 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import roomescape.auth.TokenRequest; +import roomescape.auth.TokenResponse; import java.net.URI; @@ -25,13 +27,6 @@ public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) { return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member); } - @PostMapping("/logout") - public ResponseEntity logout(HttpServletResponse response) { - Cookie cookie = new Cookie("token", ""); - cookie.setHttpOnly(true); - cookie.setPath("/"); - cookie.setMaxAge(0); - response.addCookie(cookie); - return ResponseEntity.ok().build(); - } + + } diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 6add784b..bacedd74 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -34,5 +34,17 @@ public class MissionStepTest { String token = response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; assertThat(token).isNotBlank(); + + ExtractableResponse checkResponse = RestAssured.given().log().all() + .contentType(ContentType.JSON) + .cookie("token", token) + .when().get("/login/check") + .then().log().all() + .statusCode(200) + .extract(); + + assertThat(checkResponse.body().jsonPath().getString("name")).isEqualTo("어드민"); } + + } \ No newline at end of file From df79257ca1bcdab35ac370069176c85b9f85616f Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 22:38:32 +0900 Subject: [PATCH 02/26] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/roomescape/MissionStepTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index bacedd74..a7dcf411 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -18,7 +18,7 @@ public class MissionStepTest { @Test - void 일단계() { + void loginTest() { Map params = new HashMap<>(); params.put("email", "admin@email.com"); params.put("password", "password"); From ac7b77fc2ca7464775f93457b4d29b2ac617f61b Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 22:41:57 +0900 Subject: [PATCH 03/26] =?UTF-8?q?feat:=202=EB=8B=A8=EA=B3=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/roomescape/MissionStepTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index a7dcf411..8addded3 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; +import roomescape.reservation.ReservationResponse; import java.util.HashMap; import java.util.Map; @@ -46,5 +47,55 @@ void loginTest() { assertThat(checkResponse.body().jsonPath().getString("name")).isEqualTo("어드민"); } + @Test + void reservationTest() { + String token = createToken("admin@email.com", "password"); // 일단계에서 토큰을 추출하는 로직을 메서드로 따로 만들어서 활용하세요. + + Map params = new HashMap<>(); + params.put("date", "2024-03-01"); + params.put("time", "1"); + params.put("theme", "1"); + + ExtractableResponse response = RestAssured.given().log().all() + .body(params) + .cookie("token", token) + .contentType(ContentType.JSON) + .post("/reservations") + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(201); + assertThat(response.as(ReservationResponse.class).getName()).isEqualTo("어드민"); + + params.put("name", "브라운"); + + ExtractableResponse adminResponse = RestAssured.given().log().all() + .body(params) + .cookie("token", token) + .contentType(ContentType.JSON) + .post("/reservations") + .then().log().all() + .extract(); + + assertThat(adminResponse.statusCode()).isEqualTo(201); + assertThat(adminResponse.as(ReservationResponse.class).getName()).isEqualTo("브라운"); + } + + private String createToken(String email, String password) { + Map params = new HashMap<>(); + params.put("email", email); + params.put("password", password); + + ExtractableResponse response = RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/login") + .then().log().all() + .statusCode(200) + .extract(); + + return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; + } + } \ No newline at end of file From eea343a19af21b7db9f530382b5d3058d3cea40e Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 22:53:13 +0900 Subject: [PATCH 04/26] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=98=88=EC=95=BD=20=EC=9D=91=EB=8B=B5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/LoginReservationResponse.java | 21 ++++++++++ .../reservation/ReservationController.java | 39 ++++++++++++++----- src/test/java/roomescape/MissionStepTest.java | 2 - 3 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 src/main/java/roomescape/auth/LoginReservationResponse.java diff --git a/src/main/java/roomescape/auth/LoginReservationResponse.java b/src/main/java/roomescape/auth/LoginReservationResponse.java new file mode 100644 index 00000000..c461f72a --- /dev/null +++ b/src/main/java/roomescape/auth/LoginReservationResponse.java @@ -0,0 +1,21 @@ +package roomescape.auth; + +public class LoginReservationResponse { + private String name; + + public LoginReservationResponse() { + } + + public LoginReservationResponse(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index b3bef399..d87a8d7c 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -1,5 +1,7 @@ package roomescape.reservation; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -7,17 +9,23 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import roomescape.auth.AuthService; +import roomescape.auth.LoginReservationResponse; +import roomescape.auth.LoginResponse; import java.net.URI; import java.util.List; +import java.util.Map; @RestController public class ReservationController { private final ReservationService reservationService; + private final AuthService authService; - public ReservationController(ReservationService reservationService) { + public ReservationController(ReservationService reservationService, AuthService authService) { this.reservationService = reservationService; + this.authService = authService; } @GetMapping("/reservations") @@ -26,16 +34,29 @@ public List list() { } @PostMapping("/reservations") - public ResponseEntity create(@RequestBody ReservationRequest reservationRequest) { - if (reservationRequest.getName() == null - || reservationRequest.getDate() == null - || reservationRequest.getTheme() == null - || reservationRequest.getTime() == null) { - return ResponseEntity.badRequest().build(); + public ResponseEntity makeReservation(@RequestBody Map reservationRequest, HttpServletRequest request) { + String token = null; + + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("token".equals(cookie.getName())) { + token = cookie.getValue(); + break; + } + } + } + + if (token == null) { + return ResponseEntity.status(401).build(); } - ReservationResponse reservation = reservationService.save(reservationRequest); - return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); + LoginResponse loginResponse = authService.findUserByToken(token); + + String name = reservationRequest.getOrDefault("name", loginResponse.getName()); + LoginReservationResponse loginReservationResponse = new LoginReservationResponse(name); + + return ResponseEntity.status(201).body(loginReservationResponse); } @DeleteMapping("/reservations/{id}") diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 8addded3..00a603bd 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -96,6 +96,4 @@ private String createToken(String email, String password) { return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; } - - } \ No newline at end of file From 786d9319d2a2590454795c76b0edfc401dad7af9 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 22:55:34 +0900 Subject: [PATCH 05/26] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/roomescape/MissionStepTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 00a603bd..ee767a71 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -96,4 +96,23 @@ private String createToken(String email, String password) { return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; } + + @Test + void jwtLoginTest() { + String brownToken = createToken("brown@email.com", "password"); + + RestAssured.given().log().all() + .cookie("token", brownToken) + .get("/admin") + .then().log().all() + .statusCode(401); + + String adminToken = createToken("admin@email.com", "password"); + + RestAssured.given().log().all() + .cookie("token", adminToken) + .get("/admin") + .then().log().all() + .statusCode(200); + } } \ No newline at end of file From 5bf45300a86a74b221e627073631fdad45a290a0 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Fri, 26 Jul 2024 23:28:12 +0900 Subject: [PATCH 06/26] =?UTF-8?q?feat:=20jwtTokenTest=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/auth/AuthInterceptor.java | 52 +++++++++++++++++++ .../auth/AuthInterceptorConfig.java | 20 +++++++ .../java/roomescape/auth/AuthService.java | 44 ++++++++++++++-- ...inController.java => LoginController.java} | 13 +++-- .../java/roomescape/auth/LoginResponse.java | 24 ++++++--- src/main/java/roomescape/auth/WebConfig.java | 20 +++++++ .../reservation/ReservationController.java | 5 +- 7 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 src/main/java/roomescape/auth/AuthInterceptor.java create mode 100644 src/main/java/roomescape/auth/AuthInterceptorConfig.java rename src/main/java/roomescape/auth/{TokenLoginController.java => LoginController.java} (87%) create mode 100644 src/main/java/roomescape/auth/WebConfig.java diff --git a/src/main/java/roomescape/auth/AuthInterceptor.java b/src/main/java/roomescape/auth/AuthInterceptor.java new file mode 100644 index 00000000..14b69efc --- /dev/null +++ b/src/main/java/roomescape/auth/AuthInterceptor.java @@ -0,0 +1,52 @@ +package roomescape.interceptor; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.servlet.HandlerInterceptor; +import roomescape.auth.AuthService; +import roomescape.auth.LoginResponse; + +import java.util.Arrays; + +public class AuthInterceptor implements HandlerInterceptor { + + private final AuthService authService; + + public AuthInterceptor(AuthService authService) { + this.authService = authService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + response.sendRedirect("/login"); + return false; + } + + Cookie tokenCookie = Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .findFirst() + .orElse(null); + + if (tokenCookie == null) { + response.sendRedirect("/login"); + return false; + } + + LoginResponse loginResponse = authService.findUserByToken(tokenCookie.getValue()); + + if (loginResponse == null) { + response.sendRedirect("/login"); + return false; + } + + if ("ADMIN".equals(loginResponse.getRole())) { + return true; // 관리자 페이지 접근 허용 + } else { + response.sendRedirect("/access-denied"); + return false; + } + } +} diff --git a/src/main/java/roomescape/auth/AuthInterceptorConfig.java b/src/main/java/roomescape/auth/AuthInterceptorConfig.java new file mode 100644 index 00000000..381f4fa9 --- /dev/null +++ b/src/main/java/roomescape/auth/AuthInterceptorConfig.java @@ -0,0 +1,20 @@ +package roomescape.auth; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import roomescape.interceptor.AuthInterceptor; + +@Configuration +public class AuthInterceptorConfig { + + private final AuthService authService; + + public AuthInterceptorConfig(AuthService authService) { + this.authService = authService; + } + + @Bean + public AuthInterceptor authInterceptor() { + return new AuthInterceptor(authService); + } +} diff --git a/src/main/java/roomescape/auth/AuthService.java b/src/main/java/roomescape/auth/AuthService.java index 6114305c..2780063d 100644 --- a/src/main/java/roomescape/auth/AuthService.java +++ b/src/main/java/roomescape/auth/AuthService.java @@ -1,17 +1,55 @@ package roomescape.auth; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; import org.springframework.stereotype.Service; -import roomescape.member.MemberResponse; + +import java.security.Key; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; @Service public class AuthService { + + private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); + private static final long EXPIRATION_TIME = 86400000; + public TokenResponse createToken(TokenRequest tokenRequest) { + String role = "USER"; + if ("admin@email.com".equals(tokenRequest.getEmail())) { + role = "ADMIN"; + } + + Map claims = new HashMap<>(); + claims.put("role", role); + + String token = Jwts.builder() + .setClaims(claims) + .setSubject(tokenRequest.getEmail()) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) + .signWith(SECRET_KEY) + .compact(); - String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwibmFtZSI6ImFkbWluIiwicm9sZSI6IkFETUlOIn0.cwnHsltFeEtOzMHs2Q5-ItawgvBZ140OyWecppNlLoI"; return new TokenResponse(token); } public LoginResponse findUserByToken(String token) { - return new LoginResponse("어드민"); + String role = Jwts.parserBuilder() + .setSigningKey(SECRET_KEY) + .build() + .parseClaimsJws(token) + .getBody() + .get("role", String.class); + String email = Jwts.parserBuilder() + .setSigningKey(SECRET_KEY) + .build() + .parseClaimsJws(token) + .getBody() + .getSubject(); + + return new LoginResponse(email, role); } } diff --git a/src/main/java/roomescape/auth/TokenLoginController.java b/src/main/java/roomescape/auth/LoginController.java similarity index 87% rename from src/main/java/roomescape/auth/TokenLoginController.java rename to src/main/java/roomescape/auth/LoginController.java index 4dc0648a..28035e31 100644 --- a/src/main/java/roomescape/auth/TokenLoginController.java +++ b/src/main/java/roomescape/auth/LoginController.java @@ -1,6 +1,7 @@ package roomescape.auth; - +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -10,11 +11,15 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + @RestController -public class TokenLoginController { +public class LoginController { private final AuthService authService; - public TokenLoginController(AuthService authService) { + public LoginController(AuthService authService) { this.authService = authService; } @@ -35,7 +40,7 @@ private Cookie createHttpOnlyCookie(String name, String value) { } @PostMapping("/logout") - public ResponseEntity logout(HttpServletResponse response) { + public ResponseEntity logout(HttpServletResponse response) { Cookie cookie = new Cookie("token", ""); cookie.setHttpOnly(true); cookie.setPath("/"); diff --git a/src/main/java/roomescape/auth/LoginResponse.java b/src/main/java/roomescape/auth/LoginResponse.java index 5f610da5..3c7433fb 100644 --- a/src/main/java/roomescape/auth/LoginResponse.java +++ b/src/main/java/roomescape/auth/LoginResponse.java @@ -1,20 +1,30 @@ package roomescape.auth; public class LoginResponse { - private String name; + private String email; + private String role; public LoginResponse() { } - public LoginResponse(String name) { - this.name = name; + public LoginResponse(String email, String role) { + this.email = email; + this.role = role; } - public String getName() { - return name; + public String getEmail() { + return email; } - public void setName(String name) { - this.name = name; + public String getRole() { + return role; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setRole(String role) { + this.role = role; } } diff --git a/src/main/java/roomescape/auth/WebConfig.java b/src/main/java/roomescape/auth/WebConfig.java new file mode 100644 index 00000000..d8a7fafb --- /dev/null +++ b/src/main/java/roomescape/auth/WebConfig.java @@ -0,0 +1,20 @@ +package roomescape.auth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import roomescape.interceptor.AuthInterceptor; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private AuthInterceptor authInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authInterceptor) + .addPathPatterns("/admin/**"); + } +} diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index d87a8d7c..2725dceb 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -53,8 +53,7 @@ public ResponseEntity makeReservation(@RequestBody Map LoginResponse loginResponse = authService.findUserByToken(token); - String name = reservationRequest.getOrDefault("name", loginResponse.getName()); - LoginReservationResponse loginReservationResponse = new LoginReservationResponse(name); + LoginReservationResponse loginReservationResponse = new LoginReservationResponse(loginResponse.getEmail()); return ResponseEntity.status(201).body(loginReservationResponse); } @@ -64,4 +63,6 @@ public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); return ResponseEntity.noContent().build(); } + + } From 91be93ad84598838a38e58345506fe1f8e9e03aa Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Mon, 5 Aug 2024 00:08:11 +0900 Subject: [PATCH 07/26] =?UTF-8?q?Feat:=20=EC=9C=A0=EC=A0=95=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=9D=91=EB=8B=B5=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/auth/UserResponse.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/roomescape/auth/UserResponse.java diff --git a/src/main/java/roomescape/auth/UserResponse.java b/src/main/java/roomescape/auth/UserResponse.java new file mode 100644 index 00000000..019609cb --- /dev/null +++ b/src/main/java/roomescape/auth/UserResponse.java @@ -0,0 +1,19 @@ +package roomescape.auth; + +public class UserResponse { + + private String name; + + public UserResponse() { + } + + public UserResponse(String name) { + this.name = name; + + } + + public String getName() { + return name; + } + +} From 9162bd341170c1536b2615b9095e1192e9b95bee Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Mon, 5 Aug 2024 00:09:05 +0900 Subject: [PATCH 08/26] =?UTF-8?q?Refactor:=20=ED=86=A0=ED=81=B0=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9C=A0=EC=A0=80=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/auth/AuthService.java | 14 +++++++++++ .../java/roomescape/auth/LoginController.java | 25 ++++++------------- .../auth/LoginReservationResponse.java | 5 +--- .../java/roomescape/auth/LoginResponse.java | 8 ------ 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/main/java/roomescape/auth/AuthService.java b/src/main/java/roomescape/auth/AuthService.java index 2780063d..00c42993 100644 --- a/src/main/java/roomescape/auth/AuthService.java +++ b/src/main/java/roomescape/auth/AuthService.java @@ -1,5 +1,6 @@ package roomescape.auth; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; @@ -17,6 +18,7 @@ public class AuthService { private static final long EXPIRATION_TIME = 86400000; public TokenResponse createToken(TokenRequest tokenRequest) { + String role = "USER"; if ("admin@email.com".equals(tokenRequest.getEmail())) { role = "ADMIN"; @@ -37,6 +39,7 @@ public TokenResponse createToken(TokenRequest tokenRequest) { } public LoginResponse findUserByToken(String token) { + String role = Jwts.parserBuilder() .setSigningKey(SECRET_KEY) .build() @@ -52,4 +55,15 @@ public LoginResponse findUserByToken(String token) { return new LoginResponse(email, role); } + + public UserResponse checkUserByToken(String token) { + Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); + if ("admin@email.com".equals(claims.getSubject())) { + return new UserResponse("어드민"); + } + else if ("user".equals(claims.getSubject())) { + return new UserResponse("유저"); + } + return null; + } } diff --git a/src/main/java/roomescape/auth/LoginController.java b/src/main/java/roomescape/auth/LoginController.java index 28035e31..b753ac08 100644 --- a/src/main/java/roomescape/auth/LoginController.java +++ b/src/main/java/roomescape/auth/LoginController.java @@ -5,7 +5,9 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -50,24 +52,13 @@ public ResponseEntity logout(HttpServletResponse response) { } @GetMapping("/login/check") - public ResponseEntity checkLogin(HttpServletRequest request) { - String token = null; - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if ("token".equals(cookie.getName())) { - token = cookie.getValue(); - break; - } - } - } - - if (token == null) { - return ResponseEntity.status(401).build(); + public ResponseEntity checkLogin(@CookieValue("token") String token) { + UserResponse user = authService.checkUserByToken(token); + if (user == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } + return ResponseEntity.ok(user); + } - LoginResponse loginResponse = authService.findUserByToken(token); - return ResponseEntity.ok(loginResponse); - } } diff --git a/src/main/java/roomescape/auth/LoginReservationResponse.java b/src/main/java/roomescape/auth/LoginReservationResponse.java index c461f72a..4981c187 100644 --- a/src/main/java/roomescape/auth/LoginReservationResponse.java +++ b/src/main/java/roomescape/auth/LoginReservationResponse.java @@ -1,6 +1,7 @@ package roomescape.auth; public class LoginReservationResponse { + private String name; public LoginReservationResponse() { @@ -13,9 +14,5 @@ public LoginReservationResponse(String name) { public String getName() { return name; } - - public void setName(String name) { - this.name = name; - } } diff --git a/src/main/java/roomescape/auth/LoginResponse.java b/src/main/java/roomescape/auth/LoginResponse.java index 3c7433fb..737106b9 100644 --- a/src/main/java/roomescape/auth/LoginResponse.java +++ b/src/main/java/roomescape/auth/LoginResponse.java @@ -19,12 +19,4 @@ public String getEmail() { public String getRole() { return role; } - - public void setEmail(String email) { - this.email = email; - } - - public void setRole(String role) { - this.role = role; - } } From efa199bbeec0ed87b45217329eff9b1dfb8667e4 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Mon, 5 Aug 2024 00:09:31 +0900 Subject: [PATCH 09/26] =?UTF-8?q?Refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=EC=97=90=20=EB=A7=9E=EC=B6=B0=20String=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/auth/TokenRequest.java | 8 -------- .../reservation/ReservationController.java | 16 ++++++++++++---- .../roomescape/reservation/ReservationDao.java | 4 ++-- .../reservation/ReservationRequest.java | 8 ++++---- .../reservation/ReservationService.java | 17 ++++++++++++++--- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main/java/roomescape/auth/TokenRequest.java b/src/main/java/roomescape/auth/TokenRequest.java index e955435a..fff88192 100644 --- a/src/main/java/roomescape/auth/TokenRequest.java +++ b/src/main/java/roomescape/auth/TokenRequest.java @@ -19,12 +19,4 @@ public String getEmail() { public void setEmail(String email) { this.email = email; } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } } diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 2725dceb..a57158ff 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; +import org.apache.catalina.User; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -16,6 +17,7 @@ import java.net.URI; import java.util.List; import java.util.Map; +import roomescape.auth.UserResponse; @RestController public class ReservationController { @@ -34,7 +36,7 @@ public List list() { } @PostMapping("/reservations") - public ResponseEntity makeReservation(@RequestBody Map reservationRequest, HttpServletRequest request) { + public ResponseEntity makeReservation(@RequestBody ReservationRequest reservationRequest, HttpServletRequest request) { String token = null; Cookie[] cookies = request.getCookies(); @@ -51,11 +53,17 @@ public ResponseEntity makeReservation(@RequestBody Map return ResponseEntity.status(401).build(); } - LoginResponse loginResponse = authService.findUserByToken(token); + UserResponse userResponse = authService.checkUserByToken(token); - LoginReservationResponse loginReservationResponse = new LoginReservationResponse(loginResponse.getEmail()); + ReservationResponse reservationResponse = new ReservationResponse( + 1L, + reservationRequest.getName() != null ? reservationRequest.getName() : userResponse.getName(), + reservationRequest.getTheme(), + reservationRequest.getDate(), + reservationRequest.getTime() + ); - return ResponseEntity.status(201).body(loginReservationResponse); + return ResponseEntity.status(201).body(reservationResponse); } @DeleteMapping("/reservations/{id}") diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java index a4972430..19c6b840 100644 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ b/src/main/java/roomescape/reservation/ReservationDao.java @@ -49,8 +49,8 @@ public Reservation save(ReservationRequest reservationRequest) { PreparedStatement ps = connection.prepareStatement("INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", new String[]{"id"}); ps.setString(1, reservationRequest.getDate()); ps.setString(2, reservationRequest.getName()); - ps.setLong(3, reservationRequest.getTheme()); - ps.setLong(4, reservationRequest.getTime()); + ps.setString(3, reservationRequest.getTheme()); + ps.setString(4, reservationRequest.getTime()); return ps; }, keyHolder); diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index 19f44124..bf6e1be0 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -3,8 +3,8 @@ public class ReservationRequest { private String name; private String date; - private Long theme; - private Long time; + private String theme; + private String time; public String getName() { return name; @@ -14,11 +14,11 @@ public String getDate() { return date; } - public Long getTheme() { + public String getTheme() { return theme; } - public Long getTime() { + public String getTime() { return time; } } diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index bd331332..a3a35dbb 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -14,8 +14,13 @@ public ReservationService(ReservationDao reservationDao) { public ReservationResponse save(ReservationRequest reservationRequest) { Reservation reservation = reservationDao.save(reservationRequest); - - return new ReservationResponse(reservation.getId(), reservationRequest.getName(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); + return new ReservationResponse( + reservation.getId(), + reservationRequest.getName(), + reservation.getTheme().getName(), + reservationRequest.getDate(), + reservationRequest.getTime() + ); } public void deleteById(Long id) { @@ -24,7 +29,13 @@ public void deleteById(Long id) { public List findAll() { return reservationDao.findAll().stream() - .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), it.getTime().getValue())) + .map(it -> new ReservationResponse( + it.getId(), + it.getName(), + it.getTheme().getName(), + it.getDate(), + it.getTime().getValue() + )) .toList(); } } From 47783ba6f319b74bb9c11a65e71f06414e487f65 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Tue, 6 Aug 2024 18:24:04 +0900 Subject: [PATCH 10/26] =?UTF-8?q?refactor:=20record=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/auth/LoginReservationResponse.java | 10 +++------- src/main/java/roomescape/auth/LoginResponse.java | 11 ++++------- src/main/java/roomescape/auth/TokenRequest.java | 15 ++++----------- src/main/java/roomescape/auth/TokenResponse.java | 13 +++---------- src/main/java/roomescape/auth/UserResponse.java | 10 +++------- .../java/roomescape/member/MemberRequest.java | 10 +++++----- .../java/roomescape/member/MemberResponse.java | 10 +++++----- .../reservation/ReservationRequest.java | 12 ++++++------ .../reservation/ReservationResponse.java | 13 ++++++------- 9 files changed, 39 insertions(+), 65 deletions(-) diff --git a/src/main/java/roomescape/auth/LoginReservationResponse.java b/src/main/java/roomescape/auth/LoginReservationResponse.java index 4981c187..b7e3f4f8 100644 --- a/src/main/java/roomescape/auth/LoginReservationResponse.java +++ b/src/main/java/roomescape/auth/LoginReservationResponse.java @@ -1,12 +1,8 @@ package roomescape.auth; -public class LoginReservationResponse { - - private String name; - - public LoginReservationResponse() { - } - +public record LoginReservationResponse( + String name +) { public LoginReservationResponse(String name) { this.name = name; } diff --git a/src/main/java/roomescape/auth/LoginResponse.java b/src/main/java/roomescape/auth/LoginResponse.java index 737106b9..d924cd5a 100644 --- a/src/main/java/roomescape/auth/LoginResponse.java +++ b/src/main/java/roomescape/auth/LoginResponse.java @@ -1,12 +1,9 @@ package roomescape.auth; -public class LoginResponse { - private String email; - private String role; - - public LoginResponse() { - } - +public record LoginResponse( + String email, + String role +) { public LoginResponse(String email, String role) { this.email = email; this.role = role; diff --git a/src/main/java/roomescape/auth/TokenRequest.java b/src/main/java/roomescape/auth/TokenRequest.java index fff88192..99ee9641 100644 --- a/src/main/java/roomescape/auth/TokenRequest.java +++ b/src/main/java/roomescape/auth/TokenRequest.java @@ -1,12 +1,9 @@ package roomescape.auth; -public class TokenRequest { - private String email; - private String password; - - public TokenRequest() { - } - +public record TokenRequest( + String email, + String password +) { public TokenRequest(String email, String password) { this.email = email; this.password = password; @@ -15,8 +12,4 @@ public TokenRequest(String email, String password) { public String getEmail() { return email; } - - public void setEmail(String email) { - this.email = email; - } } diff --git a/src/main/java/roomescape/auth/TokenResponse.java b/src/main/java/roomescape/auth/TokenResponse.java index 26020fcd..ffd5316f 100644 --- a/src/main/java/roomescape/auth/TokenResponse.java +++ b/src/main/java/roomescape/auth/TokenResponse.java @@ -1,11 +1,8 @@ package roomescape.auth; -public class TokenResponse { - private String accessToken; - - public TokenResponse() { - } - +public record TokenResponse( + String accessToken +) { public TokenResponse(String accessToken) { this.accessToken = accessToken; } @@ -13,8 +10,4 @@ public TokenResponse(String accessToken) { public String getAccessToken() { return accessToken; } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } } diff --git a/src/main/java/roomescape/auth/UserResponse.java b/src/main/java/roomescape/auth/UserResponse.java index 019609cb..d43e2554 100644 --- a/src/main/java/roomescape/auth/UserResponse.java +++ b/src/main/java/roomescape/auth/UserResponse.java @@ -1,12 +1,8 @@ package roomescape.auth; -public class UserResponse { - - private String name; - - public UserResponse() { - } - +public record UserResponse( + String name +) { public UserResponse(String name) { this.name = name; diff --git a/src/main/java/roomescape/member/MemberRequest.java b/src/main/java/roomescape/member/MemberRequest.java index cafb79f1..efa9223a 100644 --- a/src/main/java/roomescape/member/MemberRequest.java +++ b/src/main/java/roomescape/member/MemberRequest.java @@ -1,10 +1,10 @@ package roomescape.member; -public class MemberRequest { - private String name; - private String email; - private String password; - +public record MemberRequest( + String name, + String email, + String password +) { public String getName() { return name; } diff --git a/src/main/java/roomescape/member/MemberResponse.java b/src/main/java/roomescape/member/MemberResponse.java index b9fa3b97..e880c56f 100644 --- a/src/main/java/roomescape/member/MemberResponse.java +++ b/src/main/java/roomescape/member/MemberResponse.java @@ -1,10 +1,10 @@ package roomescape.member; -public class MemberResponse { - private Long id; - private String name; - private String email; - +public record MemberResponse( + Long id, + String name, + String email +) { public MemberResponse(Long id, String name, String email) { this.id = id; this.name = name; diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index bf6e1be0..f5bdbf64 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -1,11 +1,11 @@ package roomescape.reservation; -public class ReservationRequest { - private String name; - private String date; - private String theme; - private String time; - +public record ReservationRequest( + String name, + String date, + String theme, + String time +) { public String getName() { return name; } diff --git a/src/main/java/roomescape/reservation/ReservationResponse.java b/src/main/java/roomescape/reservation/ReservationResponse.java index 41360a36..8bf5489f 100644 --- a/src/main/java/roomescape/reservation/ReservationResponse.java +++ b/src/main/java/roomescape/reservation/ReservationResponse.java @@ -1,12 +1,11 @@ package roomescape.reservation; -public class ReservationResponse { - private Long id; - private String name; - private String theme; - private String date; - private String time; - +public record ReservationResponse( + Long id, + String name, + String theme, + String date, + String time) { public ReservationResponse(Long id, String name, String theme, String date, String time) { this.id = id; this.name = name; From b4e8cf8c32b75a897a41da37239cf7e8cbe8f5ee Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Tue, 6 Aug 2024 18:25:18 +0900 Subject: [PATCH 11/26] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/auth/AuthInterceptor.java | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/main/java/roomescape/auth/AuthInterceptor.java b/src/main/java/roomescape/auth/AuthInterceptor.java index 14b69efc..6d1f26a1 100644 --- a/src/main/java/roomescape/auth/AuthInterceptor.java +++ b/src/main/java/roomescape/auth/AuthInterceptor.java @@ -1,12 +1,14 @@ -package roomescape.interceptor; +package roomescape.auth; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.servlet.HandlerInterceptor; -import roomescape.auth.AuthService; -import roomescape.auth.LoginResponse; +import java.io.IOException; import java.util.Arrays; public class AuthInterceptor implements HandlerInterceptor { @@ -19,11 +21,40 @@ public AuthInterceptor(AuthService authService) { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + ResponseEntity authCheck = checkAuthentication(request); Cookie[] cookies = request.getCookies(); - if (cookies == null) { - response.sendRedirect("/login"); + if (authCheck != null) { + handleResponseEntity(response, authCheck); + return false; + } + + LoginResponse loginResponse = getLoginResponse(request); + + if (loginResponse == null) { + ResponseEntity loginRedirect = ResponseEntity.status(HttpStatus.FOUND) + .header(HttpHeaders.LOCATION, "/login") + .body("유저를 찾을 수 없습니다. 로그인 페이지로 이동합니다."); + handleResponseEntity(response, loginRedirect); + return false; + } + if ("ADMIN".equals(loginResponse.getRole())) { + return true; // 관리자 페이지 접근 허용 + } else { + ResponseEntity accessDenied = ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .header(HttpHeaders.LOCATION, "/access-denied") + .body("관리자 페이지입니다. 접근 권한이 없습니다."); + handleResponseEntity(response, accessDenied); return false; } + } + + private ResponseEntity checkAuthentication(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + return ResponseEntity.status(HttpStatus.FOUND) + .header(HttpHeaders.LOCATION, "/login") + .body("쿠키를 찾을 수 없습니다. 로그인 페이지로 이동합니다."); + } Cookie tokenCookie = Arrays.stream(cookies) .filter(cookie -> "token".equals(cookie.getName())) @@ -31,22 +62,29 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons .orElse(null); if (tokenCookie == null) { - response.sendRedirect("/login"); - return false; + return ResponseEntity.status(HttpStatus.FOUND) + .header(HttpHeaders.LOCATION, "/login") + .body("토큰을 찾을 수 없습니다. 로그인 페이지로 이동합니다."); } + return null; + } - LoginResponse loginResponse = authService.findUserByToken(tokenCookie.getValue()); + private LoginResponse getLoginResponse(HttpServletRequest request) { + Cookie tokenCookie = Arrays.stream(request.getCookies()) + .filter(cookie -> "token".equals(cookie.getName())) + .findFirst() + .orElse(null); - if (loginResponse == null) { - response.sendRedirect("/login"); - return false; + if (tokenCookie == null) { + return null; } - if ("ADMIN".equals(loginResponse.getRole())) { - return true; // 관리자 페이지 접근 허용 - } else { - response.sendRedirect("/access-denied"); - return false; - } + return authService.findUserByToken(tokenCookie.getValue()); + } + + private void handleResponseEntity(HttpServletResponse response, ResponseEntity entity) throws IOException, IOException { + response.setStatus(entity.getStatusCodeValue()); + response.setHeader(HttpHeaders.LOCATION, entity.getHeaders().getFirst(HttpHeaders.LOCATION)); + response.getWriter().write(entity.getBody()); } } From 152a202d83deba4f296627566f01c3aaac0b36e8 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Tue, 6 Aug 2024 18:25:33 +0900 Subject: [PATCH 12/26] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/auth/AuthInterceptorConfig.java | 1 - src/main/java/roomescape/auth/LoginController.java | 6 ------ src/main/java/roomescape/auth/WebConfig.java | 1 - 3 files changed, 8 deletions(-) diff --git a/src/main/java/roomescape/auth/AuthInterceptorConfig.java b/src/main/java/roomescape/auth/AuthInterceptorConfig.java index 381f4fa9..c862f4ec 100644 --- a/src/main/java/roomescape/auth/AuthInterceptorConfig.java +++ b/src/main/java/roomescape/auth/AuthInterceptorConfig.java @@ -2,7 +2,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import roomescape.interceptor.AuthInterceptor; @Configuration public class AuthInterceptorConfig { diff --git a/src/main/java/roomescape/auth/LoginController.java b/src/main/java/roomescape/auth/LoginController.java index b753ac08..ce3d7cc8 100644 --- a/src/main/java/roomescape/auth/LoginController.java +++ b/src/main/java/roomescape/auth/LoginController.java @@ -13,10 +13,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - @RestController public class LoginController { private final AuthService authService; @@ -59,6 +55,4 @@ public ResponseEntity checkLogin(@CookieValue("token") String toke } return ResponseEntity.ok(user); } - - } diff --git a/src/main/java/roomescape/auth/WebConfig.java b/src/main/java/roomescape/auth/WebConfig.java index d8a7fafb..5d423d08 100644 --- a/src/main/java/roomescape/auth/WebConfig.java +++ b/src/main/java/roomescape/auth/WebConfig.java @@ -4,7 +4,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import roomescape.interceptor.AuthInterceptor; @Configuration public class WebConfig implements WebMvcConfigurer { From e48972831499ff7651ac3a43e906b46553b5bad3 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Wed, 14 Aug 2024 03:52:47 +0900 Subject: [PATCH 13/26] =?UTF-8?q?Feat:=20JpaRepository=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/member/MemberRepository.java | 8 ++++++++ .../roomescape/reservation/ReservationRepository.java | 10 ++++++++++ src/main/java/roomescape/time/TimeRepository.java | 8 ++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/main/java/roomescape/member/MemberRepository.java create mode 100644 src/main/java/roomescape/reservation/ReservationRepository.java create mode 100644 src/main/java/roomescape/time/TimeRepository.java diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java new file mode 100644 index 00000000..98883030 --- /dev/null +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -0,0 +1,8 @@ +package roomescape.member; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MemberRepository extends JpaRepository { +} diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java new file mode 100644 index 00000000..fafd9407 --- /dev/null +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -0,0 +1,10 @@ +package roomescape.reservation; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReservationRepository extends JpaRepository { + List findByDateAndThemeId(String date, Long themeId); +} diff --git a/src/main/java/roomescape/time/TimeRepository.java b/src/main/java/roomescape/time/TimeRepository.java new file mode 100644 index 00000000..f668cf06 --- /dev/null +++ b/src/main/java/roomescape/time/TimeRepository.java @@ -0,0 +1,8 @@ +package roomescape.time; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TimeRepository extends JpaRepository{ +} From 863e220ef5f3f609816884491674fe2a652c9fa2 Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Wed, 14 Aug 2024 03:53:20 +0900 Subject: [PATCH 14/26] =?UTF-8?q?Feat:=20data-jpa=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- src/main/resources/application.properties | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 8d52aebc..a3dcc18a 100644 --- a/build.gradle +++ b/build.gradle @@ -15,13 +15,13 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.0.0' implementation 'io.jsonwebtoken:jjwt-api:0.11.2' implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' implementation 'io.jsonwebtoken:jjwt-gson:0.11.2' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:5.3.1' diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a0f33bba..f1f05167 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,9 +3,9 @@ spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.datasource.url=jdbc:h2:mem:database -#spring.jpa.show-sql=true -#spring.jpa.properties.hibernate.format_sql=true -#spring.jpa.ddl-auto=create-drop -#spring.jpa.defer-datasource-initialization=true +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.ddl-auto=create-drop +spring.jpa.defer-datasource-initialization=true #roomescape.auth.jwt.secret= Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= \ No newline at end of file From 98b8366b7f23eb1ffb83c02f6d5bb9a55969edfa Mon Sep 17 00:00:00 2001 From: Junyeong-An <2117ab@gmail.com> Date: Wed, 14 Aug 2024 03:54:01 +0900 Subject: [PATCH 15/26] =?UTF-8?q?Remove:=20Dao=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/member/MemberDao.java | 55 -------- .../reservation/ReservationDao.java | 127 ------------------ src/main/java/roomescape/time/TimeDao.java | 41 ------ 3 files changed, 223 deletions(-) delete mode 100644 src/main/java/roomescape/member/MemberDao.java delete mode 100644 src/main/java/roomescape/reservation/ReservationDao.java delete mode 100644 src/main/java/roomescape/time/TimeDao.java diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java deleted file mode 100644 index 81f77f4c..00000000 --- a/src/main/java/roomescape/member/MemberDao.java +++ /dev/null @@ -1,55 +0,0 @@ -package roomescape.member; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -@Repository -public class MemberDao { - private JdbcTemplate jdbcTemplate; - - public MemberDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public Member save(Member member) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, member.getName()); - ps.setString(2, member.getEmail()); - ps.setString(3, member.getPassword()); - ps.setString(4, member.getRole()); - return ps; - }, keyHolder); - - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); - } - - public Member findByEmailAndPassword(String email, String password) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - email, password - ); - } - - public Member findByName(String name) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - name - ); - } -} diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java deleted file mode 100644 index 19c6b840..00000000 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ /dev/null @@ -1,127 +0,0 @@ -package roomescape.reservation; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import roomescape.theme.Theme; -import roomescape.time.Time; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class ReservationDao { - - private final JdbcTemplate jdbcTemplate; - - public ReservationDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id", - - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } - - public Reservation save(ReservationRequest reservationRequest) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - PreparedStatement ps = connection.prepareStatement("INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, reservationRequest.getDate()); - ps.setString(2, reservationRequest.getName()); - ps.setString(3, reservationRequest.getTheme()); - ps.setString(4, reservationRequest.getTime()); - return ps; - }, keyHolder); - - Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = ?", - (rs, rowNum) -> new Time(rs.getLong("id"), rs.getString("time_value")), - reservationRequest.getTime()); - - Theme theme = jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", - (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), rs.getString("description")), - reservationRequest.getTheme()); - - return new Reservation( - keyHolder.getKey().longValue(), - reservationRequest.getName(), - reservationRequest.getDate(), - time, - theme - ); - } - - public void deleteById(Long id) { - jdbcTemplate.update("DELETE FROM reservation WHERE id = ?", id); - } - - public List findReservationsByDateAndTheme(String date, Long themeId) { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id" + - "WHERE r.date = ? AND r.theme_id = ?", - new Object[]{date, themeId}, - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } - - public List findByDateAndThemeId(String date, Long themeId) { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id " + - "WHERE r.date = ? AND r.theme_id = ?", - new Object[]{date, themeId}, - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } -} diff --git a/src/main/java/roomescape/time/TimeDao.java b/src/main/java/roomescape/time/TimeDao.java deleted file mode 100644 index f39a9a32..00000000 --- a/src/main/java/roomescape/time/TimeDao.java +++ /dev/null @@ -1,41 +0,0 @@ -package roomescape.time; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class TimeDao { - private final JdbcTemplate jdbcTemplate; - - public TimeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List