From ce4c6a1c8da137d09ec700f02864c404a4cf0a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 17:35:37 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20refresh=20token=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 10 ++ .../exception/ExpriedTokenException.java | 11 ++ .../exception/GlobalExceptionHandler.java | 27 +++++ .../exception/InvalidTokenException.java | 7 ++ .../edufocus/edufocus/user/util/JWTUtil.java | 44 ++++--- .../edufocus/video/controller/Controller.java | 108 ++++++++++++------ 6 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index b4bff53..6526a03 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -3,6 +3,8 @@ package com.edufocus.edufocus.user.controller; import com.edufocus.edufocus.user.model.entity.InfoDto; import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; @@ -258,7 +260,15 @@ public class UserController { } + @ExceptionHandler(ExpriedTokenException.class) + public ResponseEntity handleExpiredTokenException(){ + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + @ExceptionHandler(UnAuthorizedException.class) + public ResponseEntity handleUnauthorizedException(){ + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java new file mode 100644 index 0000000..e816b32 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.user.model.exception; + +public class ExpriedTokenException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ExpriedTokenException() { + super("계정 권한이 유효하지 않습니다.\n다시 로그인을 하세요."); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..526e6ae --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package com.edufocus.edufocus.user.model.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(UnAuthorizedException.class) + public ResponseEntity handleUnAuthorizedException(UnAuthorizedException e) { + + + + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + + + @ExceptionHandler(ExpriedTokenException.class) + public ResponseEntity handleInvalidTokenException(ExpriedTokenException e) { + // 로그 남기기 (선택 사항) + // log.error("Invalid token", e); + + return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java new file mode 100644 index 0000000..74969f3 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java @@ -0,0 +1,7 @@ +package com.edufocus.edufocus.user.model.exception; + +public class InvalidTokenException extends RuntimeException { + public InvalidTokenException() { + super("Token is invalid"); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index ead01db..ffce34c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -4,6 +4,8 @@ import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.Map; +import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.InvalidTokenException; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value; @@ -52,19 +54,27 @@ public class JWTUtil { public boolean checkToken(String token) { try { - Jws claims = Jwts.parserBuilder() - .setSigningKey(generateKey()) - .build() - .parseClaimsJws(token); - log.debug("claims: {}", claims); - return true; - } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException | ExpiredJwtException e) { - log.error("Token validation error: {}", e.getMessage()); - return false; - } catch (Exception e) { - System.out.println(token); - log.error("Unexpected error while validating token: {}", e.getMessage()); - return false; + Jws claims = Jwts.parserBuilder() + .setSigningKey(generateKey()) + .build() + .parseClaimsJws(token); + log.debug("claims: {}", claims); + return true; + } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException e) { + log.error("Token validation error: {}", e.getMessage()); + + return false; + } + catch ( ExpiredJwtException e) + { + throw new ExpriedTokenException(); + + } + catch (Exception e) { + System.out.println(token); + System.out.println(e.getMessage()); + log.error("Unexpected error while validating token: {}", e.getMessage()); + return false; } } @@ -77,7 +87,13 @@ public class JWTUtil { Map value = claims.getBody(); log.info("value : {}", value); return (String) value.get("id"); - } catch (Exception e) { + }catch ( ExpiredJwtException e) + { + System.out.println("expired token"); + throw new ExpriedTokenException(); + + } + catch (Exception e) { log.error("Failed to get user ID from token: {}", e.getMessage()); throw new UnAuthorizedException(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index c4fa32c..40b206a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -7,6 +7,9 @@ import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.service.LectureService; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.service.RegistrationService; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.UserRole; +import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import com.edufocus.edufocus.video.service.VideoSertvice; @@ -33,6 +36,7 @@ public class Controller { private final LectureService lectureService; private final VideoSertvice videoSertvice; private final RegistrationService registrationService; + private final UserRepository userRepository; @Value("${livekit.api.key}") private String LIVEKIT_API_KEY; @@ -70,39 +74,13 @@ public class Controller { Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - LectureDetailResponse lecture= lectureService.findLectureById(userId,id); - - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); + User findUser= userRepository.findById(userId).orElse(null); - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName); - token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName),new RoomCreate(true)); - - videoSertvice.startOnline(userId,id); + if(findUser.getRole()==UserRole.ADMIN) { + LectureDetailResponse lecture = lectureService.findLectureById(userId, id); - - - return ResponseEntity.ok(Map.of("token", token.toJwt())); - } - - - @PostMapping(value = "/joinroom/{lecture_id}") - public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { - - String userToken = request.getHeader("Authorization"); - - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - LectureDetailResponse lecture= lectureService.findLectureById(userId,id); - - - //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); - -// if(registrationStatus==RegistrationStatus.ACCEPTED) -// { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); @@ -110,23 +88,79 @@ public class Controller { AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName); token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName)); - - //videoSertvice.startOnline(userId,id); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + videoSertvice.startOnline(userId, id); return ResponseEntity.ok(Map.of("token", token.toJwt())); -// } -// else{ -// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); -// -// } + + } + else if(findUser.getRole()==UserRole.STUDENT) + { + LectureDetailResponse lecture = lectureService.findLectureById(userId, id); + + + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + + + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + token.setName(participantName); + token.setIdentity(participantName); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + + videoSertvice.startOnline(userId, id); + + + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } + + + return ResponseEntity.ok(Map.of("token", null)); } + +// @PostMapping(value = "/joinroom/{lecture_id}") +// public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { +// +//// String userToken = request.getHeader("Authorization"); +//// +//// Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); +//// LectureDetailResponse lecture= lectureService.findLectureById(userId,id); +//// +//// +//// //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); +//// +////// if(registrationStatus==RegistrationStatus.ACCEPTED) +////// { +//// String roomName = lecture.getTitle(); +//// String participantName = userService.getUserName(userId); +//// +//// +//// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); +//// token.setName(participantName); +//// token.setIdentity(participantName); +//// token.addGrants(new RoomJoin(true), new RoomName(roomName)); +//// +//// //videoSertvice.startOnline(userId,id); +//// +//// +//// +//// return ResponseEntity.ok(Map.of("token", token.toJwt())); +////// } +////// else{ +////// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); +////// +////// } +//// +// +// +// } + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET);