From 29da671a2c2430cdebe7a4c936c8486454938fd6 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 10:54:42 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[Setting]=20spring=20cache=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EC=A4=80=EB=B9=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Backend/docker-compose.yml | 7 ++++++- Backend/pom.xml | 9 +++++++++ .../java/kimjang/toolkit/solsol/SolsolApplication.java | 2 ++ Backend/src/main/resources/application-dev.properties | 7 ++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Backend/docker-compose.yml b/Backend/docker-compose.yml index 9ad3a88..ec9cb4e 100644 --- a/Backend/docker-compose.yml +++ b/Backend/docker-compose.yml @@ -16,4 +16,9 @@ services: - ./db:/var/lib/mysql container_name: chat-db ports: - - "3306:3306" \ No newline at end of file + - "3306:3306" + memcached: + container_name: solsol-memcached + image: memcached:alpine + ports: + - 11211:11211 \ No newline at end of file diff --git a/Backend/pom.xml b/Backend/pom.xml index 31e4fbe..4b5c744 100644 --- a/Backend/pom.xml +++ b/Backend/pom.xml @@ -115,6 +115,15 @@ 2.5 provided + + + + io.sixhours + memcached-spring-boot-starter + 2.5.0 + + + diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/SolsolApplication.java b/Backend/src/main/java/kimjang/toolkit/solsol/SolsolApplication.java index 0ac311c..2018084 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/SolsolApplication.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/SolsolApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +@EnableCaching @SpringBootApplication public class SolsolApplication { public static void main(String[] args) { diff --git a/Backend/src/main/resources/application-dev.properties b/Backend/src/main/resources/application-dev.properties index 3dead11..19d6f39 100644 --- a/Backend/src/main/resources/application-dev.properties +++ b/Backend/src/main/resources/application-dev.properties @@ -19,4 +19,9 @@ spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql= true # swagger -#springdoc.swagger-ui.path=/swagger-ui.html \ No newline at end of file +#springdoc.swagger-ui.path=/swagger-ui.html + +# memcached +memcached.cache.servers: memcached:11211 +memcached.cache.expirations: 3600 +memcached.cache.operation-timeout: 3000 \ No newline at end of file From 90784cc7e8335456ddc00fb8b081df31144678fa Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 11:45:59 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[Feat]=20refresh=20token=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=98=EA=B3=A0=20=EC=A0=80=EC=9E=A5=ED=95=A0=20ent?= =?UTF-8?q?ity=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solsol/config/handler/StompHandler.java | 5 +-- ...stomUserNamePwdAuthenticationProvider.java | 6 ++-- .../solsol/domain/cache/RefreshToken.java | 24 +++++++++++++ .../cache/RefreshTokenCacheService.java | 18 ++++++++++ .../domain/cache/RefreshTokenRepository.java | 7 ++++ .../{ => domain}/message/ChatMessage.java | 8 ++--- .../solsol/{ => domain}/message/Greeting.java | 2 +- .../message/GreetingController.java | 6 +--- .../{ => domain}/message/HelloMessage.java | 2 +- .../message/controllor/ChatController.java | 12 +++---- .../{ => domain}/message/dto/GetChatProj.java | 4 +-- .../message/dto/PastChatsDto.java | 2 +- .../message/dto/ReqPastChatsDto.java | 2 +- .../message/dto/SendChatMessageDto.java | 4 +-- .../message/repository/ChatRepository.java | 7 ++-- .../message/service/ChatService.java | 20 +++++------ .../{ => domain}/room/ChatRoomController.java | 14 +++++--- .../{ => domain}/room/dto/ChatRoomDto.java | 2 +- .../room/dto/CreateChatRoomDto.java | 3 +- .../room/dto/CreateRoomReqDto.java | 4 +-- .../room/dto/InviteChatRoomDto.java | 4 +-- .../{ => domain}/room/dto/LastChatDto.java | 2 +- .../{ => domain}/room/dto/LeaveRoomDto.java | 4 +-- .../room/dto/ReqChatRoomMetaDTO.java | 4 +-- .../{ => domain}/room/entity/ChatRoom.java | 2 +- .../entity/ChatRoomCustomerRelationship.java | 4 +-- ...atRoomCustormerRelationshipRepository.java | 4 +-- .../room/repository/ChatRoomRepository.java | 6 ++-- .../room/service/ChatRoomService.java | 30 ++++++++-------- .../room/service/ChatRoomStompService.java | 11 ++---- .../service/ChatRoomSubscribeService.java | 6 ++-- .../room/service/CreateRoomName.java | 7 ++-- .../user/controller/UserController.java | 11 +++--- .../{ => domain}/user/dto/AddFriendsDto.java | 2 +- .../{ => domain}/user/dto/CreateUserDto.java | 2 +- .../solsol/domain/user/dto/IssuedTokens.java | 15 ++++++++ .../{ => domain}/user/dto/LoginDto.java | 2 +- .../user/dto/LoginSuccessDto.java | 2 +- .../{ => domain}/user/dto/RefreshDto.java | 2 +- .../solsol/{ => domain}/user/dto/UserDto.java | 4 +-- .../{ => domain}/user/dto/UserProfileDto.java | 2 +- .../{ => domain}/user/entities/Authority.java | 2 +- .../{ => domain}/user/entities/Friend.java | 2 +- .../{ => domain}/user/entities/User.java | 4 +-- .../user/reposiotry/FriendRepository.java | 6 ++-- .../user/reposiotry/UserRepository.java | 6 ++-- .../user/service/FriendService.java | 14 ++++---- .../{ => domain}/user/service/JwtIssuer.java | 34 +++++++++++------- .../user/service/UserService.java | 35 +++++++++++++++---- .../toolkit/solsol/chat/CreateChatTest.java | 8 ++--- .../toolkit/solsol/chat/GetPastChatsTest.java | 8 ++--- .../solsol/chat/LoadPastChatsTest.java | 6 ++-- .../InviteIntegrationTests.java | 12 +++---- .../MessageIntegrationTests.java | 4 +-- .../toolkit/solsol/room/ChatRoomListTest.java | 4 +-- .../toolkit/solsol/room/CreateRoomTest.java | 15 +++----- .../toolkit/solsol/user/UniqueEmailTest.java | 3 +- 57 files changed, 252 insertions(+), 189 deletions(-) create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/ChatMessage.java (85%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/Greeting.java (80%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/GreetingController.java (77%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/HelloMessage.java (84%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/controllor/ChatController.java (84%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/dto/GetChatProj.java (74%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/dto/PastChatsDto.java (94%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/dto/ReqPastChatsDto.java (94%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/dto/SendChatMessageDto.java (94%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/repository/ChatRepository.java (93%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/message/service/ChatService.java (74%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/ChatRoomController.java (84%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/ChatRoomDto.java (92%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/CreateChatRoomDto.java (78%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/CreateRoomReqDto.java (86%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/InviteChatRoomDto.java (86%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/LastChatDto.java (85%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/LeaveRoomDto.java (68%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/dto/ReqChatRoomMetaDTO.java (68%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/entity/ChatRoom.java (95%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/entity/ChatRoomCustomerRelationship.java (87%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/repository/ChatRoomCustormerRelationshipRepository.java (78%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/repository/ChatRoomRepository.java (89%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/service/ChatRoomService.java (84%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/service/ChatRoomStompService.java (77%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/service/ChatRoomSubscribeService.java (75%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/room/service/CreateRoomName.java (89%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/controller/UserController.java (88%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/AddFriendsDto.java (82%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/CreateUserDto.java (92%) create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/IssuedTokens.java rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/LoginDto.java (81%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/LoginSuccessDto.java (92%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/RefreshDto.java (65%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/UserDto.java (88%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/dto/UserProfileDto.java (91%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/entities/Authority.java (92%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/entities/Friend.java (94%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/entities/User.java (94%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/reposiotry/FriendRepository.java (81%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/reposiotry/UserRepository.java (81%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/service/FriendService.java (78%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/service/JwtIssuer.java (87%) rename Backend/src/main/java/kimjang/toolkit/solsol/{ => domain}/user/service/UserService.java (72%) diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/handler/StompHandler.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/handler/StompHandler.java index 222a28c..17ac705 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/config/handler/StompHandler.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/handler/StompHandler.java @@ -1,7 +1,7 @@ package kimjang.toolkit.solsol.config.handler; -import kimjang.toolkit.solsol.room.service.ChatRoomSubscribeService; +import kimjang.toolkit.solsol.domain.room.service.ChatRoomSubscribeService; import kimjang.toolkit.solsol.config.container.SocketSessionContainer; import kimjang.toolkit.solsol.config.jwt.SecurityConstants; import kimjang.toolkit.solsol.config.provider.JwtAuthenticationProvider; @@ -9,12 +9,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.simp.stomp.StompCommand; import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptor; -import org.springframework.security.authentication.BadCredentialsException; -import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/provider/CustomUserNamePwdAuthenticationProvider.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/provider/CustomUserNamePwdAuthenticationProvider.java index e3e4313..e6015d1 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/config/provider/CustomUserNamePwdAuthenticationProvider.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/provider/CustomUserNamePwdAuthenticationProvider.java @@ -1,8 +1,8 @@ package kimjang.toolkit.solsol.config.provider; -import kimjang.toolkit.solsol.user.entities.Authority; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.user.reposiotry.UserRepository; +import kimjang.toolkit.solsol.domain.user.entities.Authority; +import kimjang.toolkit.solsol.domain.user.entities.User; +import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java new file mode 100644 index 0000000..e8d13a4 --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java @@ -0,0 +1,24 @@ +package kimjang.toolkit.solsol.domain.cache; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RefreshToken { + @Id + @GeneratedValue(strategy = GenerationType.AUTO, generator = "native") + @Column(name = "token_id") // 컬럼의 이름을 바꿀 수 있다. + private Long id; + + private String email; + + @Column(name = "refresh_token") + private String refreshToken; +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java new file mode 100644 index 0000000..ad95b51 --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java @@ -0,0 +1,18 @@ +package kimjang.toolkit.solsol.domain.cache; + +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RefreshTokenCacheService { + + private final RefreshTokenRepository refreshTokenRepository; + + @Cacheable(value = "refresh") + public String findRefreshToken(String email){ + return + } + +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java new file mode 100644 index 0000000..8efe676 --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java @@ -0,0 +1,7 @@ +package kimjang.toolkit.solsol.domain.cache; + +import org.springframework.stereotype.Repository; + +@Repository +public interface RefreshTokenRepository { +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/ChatMessage.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/ChatMessage.java similarity index 85% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/ChatMessage.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/ChatMessage.java index cf2e979..b836d1b 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/ChatMessage.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/ChatMessage.java @@ -1,9 +1,9 @@ -package kimjang.toolkit.solsol.message; +package kimjang.toolkit.solsol.domain.message; import jakarta.persistence.*; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; -import kimjang.toolkit.solsol.room.entity.ChatRoom; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoom; +import kimjang.toolkit.solsol.domain.user.entities.User; import lombok.*; import java.time.LocalDateTime; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/Greeting.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/Greeting.java similarity index 80% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/Greeting.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/Greeting.java index ce71e2a..62dd4d5 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/Greeting.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/Greeting.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.message; +package kimjang.toolkit.solsol.domain.message; public class Greeting { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/GreetingController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/GreetingController.java similarity index 77% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/GreetingController.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/GreetingController.java index 2afccad..00dc0ad 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/GreetingController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/GreetingController.java @@ -1,12 +1,8 @@ -package kimjang.toolkit.solsol.message; +package kimjang.toolkit.solsol.domain.message; -import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.HtmlUtils; @Controller public class GreetingController { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/HelloMessage.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/HelloMessage.java similarity index 84% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/HelloMessage.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/HelloMessage.java index 605b2c5..b4a3efb 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/HelloMessage.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/HelloMessage.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.message; +package kimjang.toolkit.solsol.domain.message; public class HelloMessage { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/controllor/ChatController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/controllor/ChatController.java similarity index 84% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/controllor/ChatController.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/controllor/ChatController.java index 97a1c0c..1bcc93b 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/controllor/ChatController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/controllor/ChatController.java @@ -1,19 +1,15 @@ -package kimjang.toolkit.solsol.message.controllor; +package kimjang.toolkit.solsol.domain.message.controllor; -import kimjang.toolkit.solsol.message.dto.PastChatsDto; -import kimjang.toolkit.solsol.message.dto.ReqPastChatsDto; -import kimjang.toolkit.solsol.message.service.ChatService; +import kimjang.toolkit.solsol.domain.message.dto.ReqPastChatsDto; +import kimjang.toolkit.solsol.domain.message.service.ChatService; +import kimjang.toolkit.solsol.domain.message.dto.PastChatsDto; import lombok.RequiredArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.time.LocalDateTime; -import java.util.Date; - @RestController @RequiredArgsConstructor public class ChatController { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/GetChatProj.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/GetChatProj.java similarity index 74% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/dto/GetChatProj.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/GetChatProj.java index 1514538..3d8c228 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/GetChatProj.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/GetChatProj.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.message.dto; +package kimjang.toolkit.solsol.domain.message.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import java.time.LocalDateTime; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/PastChatsDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/PastChatsDto.java similarity index 94% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/dto/PastChatsDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/PastChatsDto.java index 87e864b..ab1ded8 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/PastChatsDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/PastChatsDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.message.dto; +package kimjang.toolkit.solsol.domain.message.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/ReqPastChatsDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/ReqPastChatsDto.java similarity index 94% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/dto/ReqPastChatsDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/ReqPastChatsDto.java index 507b83e..c56aa28 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/ReqPastChatsDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/ReqPastChatsDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.message.dto; +package kimjang.toolkit.solsol.domain.message.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/SendChatMessageDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/SendChatMessageDto.java similarity index 94% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/dto/SendChatMessageDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/SendChatMessageDto.java index edac1ff..97e6620 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/dto/SendChatMessageDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/dto/SendChatMessageDto.java @@ -1,9 +1,9 @@ -package kimjang.toolkit.solsol.message.dto; +package kimjang.toolkit.solsol.domain.message.dto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import lombok.*; import java.time.LocalDateTime; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/repository/ChatRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java similarity index 93% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/repository/ChatRepository.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java index 3c48083..9a81ee4 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/repository/ChatRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.message.repository; +package kimjang.toolkit.solsol.domain.message.repository; -import kimjang.toolkit.solsol.message.ChatMessage; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; +import kimjang.toolkit.solsol.domain.message.ChatMessage; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -10,7 +10,6 @@ import org.springframework.stereotype.Repository; import java.util.List; -import java.util.Optional; @Repository public interface ChatRepository extends JpaRepository { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/message/service/ChatService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/service/ChatService.java similarity index 74% rename from Backend/src/main/java/kimjang/toolkit/solsol/message/service/ChatService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/message/service/ChatService.java index 1c45a1f..a233b3c 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/message/service/ChatService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/service/ChatService.java @@ -1,14 +1,14 @@ -package kimjang.toolkit.solsol.message.service; +package kimjang.toolkit.solsol.domain.message.service; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.user.reposiotry.UserRepository; -import kimjang.toolkit.solsol.message.ChatMessage; -import kimjang.toolkit.solsol.message.dto.PastChatsDto; -import kimjang.toolkit.solsol.message.dto.ReqPastChatsDto; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; -import kimjang.toolkit.solsol.message.repository.ChatRepository; -import kimjang.toolkit.solsol.room.entity.ChatRoom; -import kimjang.toolkit.solsol.room.repository.ChatRoomRepository; +import kimjang.toolkit.solsol.domain.message.dto.ReqPastChatsDto; +import kimjang.toolkit.solsol.domain.message.repository.ChatRepository; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoom; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomRepository; +import kimjang.toolkit.solsol.domain.user.entities.User; +import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; +import kimjang.toolkit.solsol.domain.message.ChatMessage; +import kimjang.toolkit.solsol.domain.message.dto.PastChatsDto; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Slice; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/ChatRoomController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java similarity index 84% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/ChatRoomController.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java index 840d4f5..94ee5dc 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/ChatRoomController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java @@ -1,10 +1,14 @@ -package kimjang.toolkit.solsol.room; +package kimjang.toolkit.solsol.domain.room; +import kimjang.toolkit.solsol.domain.room.dto.ChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.LeaveRoomDto; import kimjang.toolkit.solsol.room.dto.*; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; -import kimjang.toolkit.solsol.room.service.ChatRoomService; -import kimjang.toolkit.solsol.room.service.ChatRoomStompService; -import kimjang.toolkit.solsol.message.service.ChatService; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; +import kimjang.toolkit.solsol.domain.room.service.ChatRoomService; +import kimjang.toolkit.solsol.domain.room.service.ChatRoomStompService; +import kimjang.toolkit.solsol.domain.message.service.ChatService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ChatRoomDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ChatRoomDto.java similarity index 92% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ChatRoomDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ChatRoomDto.java index acbea4f..8bf8522 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ChatRoomDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ChatRoomDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateChatRoomDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateChatRoomDto.java similarity index 78% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateChatRoomDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateChatRoomDto.java index 7a163a3..093a430 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateChatRoomDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateChatRoomDto.java @@ -1,6 +1,5 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateRoomReqDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateRoomReqDto.java similarity index 86% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateRoomReqDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateRoomReqDto.java index e51b470..00cc039 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/CreateRoomReqDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/CreateRoomReqDto.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/InviteChatRoomDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/InviteChatRoomDto.java similarity index 86% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/InviteChatRoomDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/InviteChatRoomDto.java index 96ade9d..ad98f66 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/InviteChatRoomDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/InviteChatRoomDto.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LastChatDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LastChatDto.java similarity index 85% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LastChatDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LastChatDto.java index a7dfb45..6528b51 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LastChatDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LastChatDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LeaveRoomDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LeaveRoomDto.java similarity index 68% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LeaveRoomDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LeaveRoomDto.java index 6dcefca..d0a77f7 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/LeaveRoomDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/LeaveRoomDto.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ReqChatRoomMetaDTO.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ReqChatRoomMetaDTO.java similarity index 68% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ReqChatRoomMetaDTO.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ReqChatRoomMetaDTO.java index a8fe308..bab8ecc 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/dto/ReqChatRoomMetaDTO.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/dto/ReqChatRoomMetaDTO.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.room.dto; +package kimjang.toolkit.solsol.domain.room.dto; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoom.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoom.java similarity index 95% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoom.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoom.java index 98eee37..a0027c0 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoom.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoom.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.room.entity; +package kimjang.toolkit.solsol.domain.room.entity; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoomCustomerRelationship.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoomCustomerRelationship.java similarity index 87% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoomCustomerRelationship.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoomCustomerRelationship.java index 6a2a9e1..3ed5d9a 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/entity/ChatRoomCustomerRelationship.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/entity/ChatRoomCustomerRelationship.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.room.entity; +package kimjang.toolkit.solsol.domain.room.entity; import jakarta.persistence.*; -import kimjang.toolkit.solsol.user.entities.User; +import kimjang.toolkit.solsol.domain.user.entities.User; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomCustormerRelationshipRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomCustormerRelationshipRepository.java similarity index 78% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomCustormerRelationshipRepository.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomCustormerRelationshipRepository.java index b4b5cab..07cbb26 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomCustormerRelationshipRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomCustormerRelationshipRepository.java @@ -1,6 +1,6 @@ -package kimjang.toolkit.solsol.room.repository; +package kimjang.toolkit.solsol.domain.room.repository; -import kimjang.toolkit.solsol.room.entity.ChatRoomCustomerRelationship; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoomCustomerRelationship; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java similarity index 89% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomRepository.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java index a2a2257..38fb188 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/repository/ChatRoomRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.room.repository; +package kimjang.toolkit.solsol.domain.room.repository; -import kimjang.toolkit.solsol.room.dto.ChatRoomDto; -import kimjang.toolkit.solsol.room.entity.ChatRoom; +import kimjang.toolkit.solsol.domain.room.dto.ChatRoomDto; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoom; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomService.java similarity index 84% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomService.java index 317cd12..b2f454c 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomService.java @@ -1,18 +1,18 @@ -package kimjang.toolkit.solsol.room.service; - -import kimjang.toolkit.solsol.room.dto.InviteChatRoomDto; -import kimjang.toolkit.solsol.room.dto.LeaveRoomDto; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.user.reposiotry.UserRepository; -import kimjang.toolkit.solsol.user.dto.UserDto; -import kimjang.toolkit.solsol.message.ChatMessage; -import kimjang.toolkit.solsol.message.repository.ChatRepository; -import kimjang.toolkit.solsol.room.dto.ChatRoomDto; -import kimjang.toolkit.solsol.room.entity.ChatRoom; -import kimjang.toolkit.solsol.room.entity.ChatRoomCustomerRelationship; -import kimjang.toolkit.solsol.room.dto.CreateChatRoomDto; -import kimjang.toolkit.solsol.room.repository.ChatRoomCustormerRelationshipRepository; -import kimjang.toolkit.solsol.room.repository.ChatRoomRepository; +package kimjang.toolkit.solsol.domain.room.service; + +import kimjang.toolkit.solsol.domain.room.dto.ChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoomCustomerRelationship; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomRepository; +import kimjang.toolkit.solsol.domain.user.entities.User; +import kimjang.toolkit.solsol.domain.room.dto.LeaveRoomDto; +import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.message.ChatMessage; +import kimjang.toolkit.solsol.domain.message.repository.ChatRepository; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoom; +import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomCustormerRelationshipRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomStompService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomStompService.java similarity index 77% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomStompService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomStompService.java index 88635bb..4f953d0 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomStompService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomStompService.java @@ -1,19 +1,14 @@ -package kimjang.toolkit.solsol.room.service; +package kimjang.toolkit.solsol.domain.room.service; -import kimjang.toolkit.solsol.room.dto.CreateChatRoomDto; -import kimjang.toolkit.solsol.room.dto.CreateRoomReqDto; -import kimjang.toolkit.solsol.room.dto.InviteChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.CreateRoomReqDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -import static kimjang.toolkit.solsol.room.service.CreateRoomName.withParticipationsName; @Slf4j @Service diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomSubscribeService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomSubscribeService.java similarity index 75% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomSubscribeService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomSubscribeService.java index 92c6fc1..1cde53e 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/ChatRoomSubscribeService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/ChatRoomSubscribeService.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.room.service; +package kimjang.toolkit.solsol.domain.room.service; -import kimjang.toolkit.solsol.room.entity.ChatRoomCustomerRelationship; -import kimjang.toolkit.solsol.room.repository.ChatRoomCustormerRelationshipRepository; +import kimjang.toolkit.solsol.domain.room.entity.ChatRoomCustomerRelationship; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomCustormerRelationshipRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/CreateRoomName.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/CreateRoomName.java similarity index 89% rename from Backend/src/main/java/kimjang/toolkit/solsol/room/service/CreateRoomName.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/CreateRoomName.java index 67152a8..0d03a0e 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/room/service/CreateRoomName.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/service/CreateRoomName.java @@ -1,9 +1,6 @@ -package kimjang.toolkit.solsol.room.service; +package kimjang.toolkit.solsol.domain.room.service; -import kimjang.toolkit.solsol.user.dto.UserDto; -import kimjang.toolkit.solsol.room.dto.CreateChatRoomDto; - -import java.util.List; +import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; public class CreateRoomName { diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/controller/UserController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java similarity index 88% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/controller/UserController.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java index 324e08b..b54dc7f 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/controller/UserController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java @@ -1,9 +1,9 @@ -package kimjang.toolkit.solsol.user.controller; +package kimjang.toolkit.solsol.domain.user.controller; -import jakarta.servlet.http.HttpServletResponse; +import kimjang.toolkit.solsol.domain.user.dto.*; +import kimjang.toolkit.solsol.domain.user.service.FriendService; import kimjang.toolkit.solsol.user.dto.*; -import kimjang.toolkit.solsol.user.service.FriendService; -import kimjang.toolkit.solsol.user.service.UserService; +import kimjang.toolkit.solsol.domain.user.service.UserService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -11,11 +11,8 @@ import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; -import java.net.http.HttpResponse; import java.util.List; -import static kimjang.toolkit.solsol.config.jwt.SecurityConstants.JWT_REFRESH_HEADER; - @Slf4j @RestController @RequiredArgsConstructor diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/AddFriendsDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AddFriendsDto.java similarity index 82% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/AddFriendsDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AddFriendsDto.java index 585c41f..57ed5bf 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/AddFriendsDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AddFriendsDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/CreateUserDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/CreateUserDto.java similarity index 92% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/CreateUserDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/CreateUserDto.java index c511fa1..9b3561d 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/CreateUserDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/CreateUserDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/IssuedTokens.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/IssuedTokens.java new file mode 100644 index 0000000..7d7c669 --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/IssuedTokens.java @@ -0,0 +1,15 @@ +package kimjang.toolkit.solsol.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class IssuedTokens { + private String accessToken; + private String refreshToken; +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginDto.java similarity index 81% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginDto.java index d40624c..e17de22 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginSuccessDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginSuccessDto.java similarity index 92% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginSuccessDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginSuccessDto.java index fa58d63..d66ebab 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/LoginSuccessDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/LoginSuccessDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/RefreshDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java similarity index 65% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/RefreshDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java index f996bae..553e115 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/RefreshDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserDto.java similarity index 88% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserDto.java index 4aa28fe..a1ce41d 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserDto.java @@ -1,8 +1,8 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; -import kimjang.toolkit.solsol.user.entities.User; +import kimjang.toolkit.solsol.domain.user.entities.User; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserProfileDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserProfileDto.java similarity index 91% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserProfileDto.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserProfileDto.java index c6af763..8b49c93 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/dto/UserProfileDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/UserProfileDto.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.dto; +package kimjang.toolkit.solsol.domain.user.dto; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Authority.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Authority.java similarity index 92% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Authority.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Authority.java index f111299..b0e861d 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Authority.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Authority.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.entities; +package kimjang.toolkit.solsol.domain.user.entities; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Friend.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Friend.java similarity index 94% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Friend.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Friend.java index 8b734c1..49884b3 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/Friend.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/Friend.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.entities; +package kimjang.toolkit.solsol.domain.user.entities; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/User.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/User.java similarity index 94% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/entities/User.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/User.java index 32f28ad..f992882 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/entities/User.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/entities/User.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.user.entities; +package kimjang.toolkit.solsol.domain.user.entities; import jakarta.persistence.*; -import kimjang.toolkit.solsol.user.dto.CreateUserDto; +import kimjang.toolkit.solsol.domain.user.dto.CreateUserDto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/FriendRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java similarity index 81% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/FriendRepository.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java index c42659a..dce3e29 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/FriendRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.user.reposiotry; +package kimjang.toolkit.solsol.domain.user.reposiotry; -import kimjang.toolkit.solsol.user.entities.Friend; -import kimjang.toolkit.solsol.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.entities.Friend; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/UserRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java similarity index 81% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/UserRepository.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java index 9c8cef6..b11eb77 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/reposiotry/UserRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java @@ -1,7 +1,7 @@ -package kimjang.toolkit.solsol.user.reposiotry; +package kimjang.toolkit.solsol.domain.user.reposiotry; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.entities.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/FriendService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/FriendService.java similarity index 78% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/service/FriendService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/FriendService.java index 94ddd95..a82d402 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/FriendService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/FriendService.java @@ -1,11 +1,11 @@ -package kimjang.toolkit.solsol.user.service; +package kimjang.toolkit.solsol.domain.user.service; -import kimjang.toolkit.solsol.user.entities.Friend; -import kimjang.toolkit.solsol.user.entities.User; -import kimjang.toolkit.solsol.user.reposiotry.FriendRepository; -import kimjang.toolkit.solsol.user.reposiotry.UserRepository; -import kimjang.toolkit.solsol.user.dto.AddFriendsDto; -import kimjang.toolkit.solsol.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.dto.AddFriendsDto; +import kimjang.toolkit.solsol.domain.user.dto.UserProfileDto; +import kimjang.toolkit.solsol.domain.user.entities.Friend; +import kimjang.toolkit.solsol.domain.user.entities.User; +import kimjang.toolkit.solsol.domain.user.reposiotry.FriendRepository; +import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java similarity index 87% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/service/JwtIssuer.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index dc299a4..ea1d1c9 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -1,4 +1,4 @@ -package kimjang.toolkit.solsol.user.service; +package kimjang.toolkit.solsol.domain.user.service; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; @@ -8,9 +8,10 @@ import io.jsonwebtoken.security.SignatureException; import kimjang.toolkit.solsol.config.jwt.JwtInvalidException; import kimjang.toolkit.solsol.config.jwt.SecurityConstants; -import kimjang.toolkit.solsol.user.entities.Authority; -import kimjang.toolkit.solsol.user.dto.LoginSuccessDto; -import kimjang.toolkit.solsol.user.dto.RefreshDto; +import kimjang.toolkit.solsol.domain.user.dto.IssuedTokens; +import kimjang.toolkit.solsol.domain.user.dto.LoginSuccessDto; +import kimjang.toolkit.solsol.domain.user.dto.RefreshDto; +import kimjang.toolkit.solsol.domain.user.entities.Authority; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -51,14 +52,6 @@ private String getToken(String email, String authorities, Long expireTime) { .signWith(key).compact(); } - private String populateAuthorities(Set collection) { - Set authoritiesSet = new HashSet<>(); - for (Authority authority : collection) { - authoritiesSet.add(authority.getName()); - } - return String.join(",", authoritiesSet); - } - public String getAccessToken(String email, Set authorities) { log.info("유통기한 : {}",accessExpireMin*ONE_MINUTE); return getToken(email, populateAuthorities(authorities), accessExpireMin*ONE_MINUTE); @@ -101,4 +94,21 @@ public LoginSuccessDto getAccessTokenByRefreshToken(RefreshDto refreshDto) { } } + + private String populateAuthorities(Set collection) { + Set authoritiesSet = new HashSet<>(); + for (Authority authority : collection) { + authoritiesSet.add(authority.getName()); + } + return String.join(",", authoritiesSet); + } + + public IssuedTokens getAccessTokenByUserInfo(String email, Set authorities) { + String accessToken = getAccessToken(email, authorities); + String refreshToken = getRefreshToken(email, authorities); + return IssuedTokens.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/UserService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java similarity index 72% rename from Backend/src/main/java/kimjang/toolkit/solsol/user/service/UserService.java rename to Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java index 955a895..19b1cec 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/user/service/UserService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java @@ -1,9 +1,11 @@ -package kimjang.toolkit.solsol.user.service; +package kimjang.toolkit.solsol.domain.user.service; +import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; +import kimjang.toolkit.solsol.domain.user.dto.*; import kimjang.toolkit.solsol.exception.UnauthorizedException; -import kimjang.toolkit.solsol.user.entities.User; +import kimjang.toolkit.solsol.domain.user.entities.User; import kimjang.toolkit.solsol.user.dto.*; -import kimjang.toolkit.solsol.user.reposiotry.UserRepository; +import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.BadCredentialsException; @@ -23,6 +25,8 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final JwtIssuer jwtIssuer; + private final RefreshTokenCacheService refreshTokenCacheService; + @Transactional public UserDto registerUser(CreateUserDto createUserDto){ String hashPwd = passwordEncoder.encode(createUserDto.getPwd()); @@ -44,6 +48,12 @@ public UserDto findByEmail(String email){ return UserDto.toDto(user); } + /** + * 유저가 처음으로 로그인할 때 생성되는 로그인 결과 값 LoginSuccessDto + * + * @param loginDto + * @return + */ public LoginSuccessDto userLoginAndSaveRefreshToken(LoginDto loginDto){ try{ User user = userRepository.findByEmail(loginDto.getEmail()) @@ -53,22 +63,33 @@ public LoginSuccessDto userLoginAndSaveRefreshToken(LoginDto loginDto){ throw new BadCredentialsException("bad credential: using unmatched password"); } log.info("email : "+loginDto.getEmail()); - String accessToken = jwtIssuer.getAccessToken(user.getEmail(), user.getAuthorities()); - String refreshToken = jwtIssuer.getRefreshToken(user.getEmail(), user.getAuthorities()); + IssuedTokens tokens = jwtIssuer.getAccessTokenByUserInfo(user.getEmail(), user.getAuthorities()); return LoginSuccessDto.builder() .id(user.getId()) .email(user.getEmail()) .name(user.getName()) .imgUrl(user.getImgUrl()) - .accessToken(accessToken) - .refreshToken(refreshToken) + .accessToken(tokens.getAccessToken()) + .refreshToken(tokens.getRefreshToken()) .build(); } catch (AuthenticationException e){ throw new RuntimeException(e.getMessage(), e); } } + /** + * 기존 refresh token으로 새로운 로그인 결과 값 LoginSuccessDto을 생성 + * @param refreshDto + * @return + */ public LoginSuccessDto getAccessToken(RefreshDto refreshDto) { + /** + * 캐시나 DB에 존재하는 refresh token인지 확인 + * - 없으면 401 에러 + * - 있으면 기존꺼 지우고 새로운 값으로 업데이트 (Cacheput) + * - refresh token의 만료시간까지 사용되지 않으면 제거 + */ + return jwtIssuer.getAccessTokenByRefreshToken(refreshDto); } diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/chat/CreateChatTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/chat/CreateChatTest.java index 0cd6305..903f15b 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/chat/CreateChatTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/chat/CreateChatTest.java @@ -2,10 +2,10 @@ import kimjang.toolkit.solsol.SolsolApplication; -import kimjang.toolkit.solsol.user.dto.UserDto; -import kimjang.toolkit.solsol.message.ChatMessage; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; -import kimjang.toolkit.solsol.message.service.ChatService; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.message.ChatMessage; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; +import kimjang.toolkit.solsol.domain.message.service.ChatService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/chat/GetPastChatsTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/chat/GetPastChatsTest.java index c233b7f..a97fae2 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/chat/GetPastChatsTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/chat/GetPastChatsTest.java @@ -1,17 +1,15 @@ package kimjang.toolkit.solsol.chat; -import kimjang.toolkit.solsol.message.dto.PastChatsDto; -import kimjang.toolkit.solsol.message.dto.ReqPastChatsDto; -import kimjang.toolkit.solsol.message.service.ChatService; +import kimjang.toolkit.solsol.domain.message.dto.PastChatsDto; +import kimjang.toolkit.solsol.domain.message.dto.ReqPastChatsDto; +import kimjang.toolkit.solsol.domain.message.service.ChatService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; -import java.time.LocalDateTime; - @SpringBootTest public class GetPastChatsTest { @Autowired diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/chat/LoadPastChatsTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/chat/LoadPastChatsTest.java index e622927..659d68d 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/chat/LoadPastChatsTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/chat/LoadPastChatsTest.java @@ -1,8 +1,8 @@ package kimjang.toolkit.solsol.chat; -import kimjang.toolkit.solsol.message.dto.PastChatsDto; -import kimjang.toolkit.solsol.message.dto.ReqPastChatsDto; -import kimjang.toolkit.solsol.message.service.ChatService; +import kimjang.toolkit.solsol.domain.message.dto.PastChatsDto; +import kimjang.toolkit.solsol.domain.message.dto.ReqPastChatsDto; +import kimjang.toolkit.solsol.domain.message.service.ChatService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/InviteIntegrationTests.java b/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/InviteIntegrationTests.java index 0799a52..adfcd61 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/InviteIntegrationTests.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/InviteIntegrationTests.java @@ -3,14 +3,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import kimjang.toolkit.solsol.message.ChatMessage; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; -import kimjang.toolkit.solsol.room.ChatRoomController; -import kimjang.toolkit.solsol.room.dto.CreateChatRoomDto; -import kimjang.toolkit.solsol.room.dto.CreateRoomReqDto; -import kimjang.toolkit.solsol.room.dto.InviteChatRoomDto; -import kimjang.toolkit.solsol.room.service.ChatRoomService; -import kimjang.toolkit.solsol.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.room.ChatRoomController; +import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.CreateRoomReqDto; +import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/MessageIntegrationTests.java b/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/MessageIntegrationTests.java index 4343657..6131993 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/MessageIntegrationTests.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/integrationTest/MessageIntegrationTests.java @@ -3,8 +3,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import kimjang.toolkit.solsol.user.dto.UserDto; -import kimjang.toolkit.solsol.message.dto.SendChatMessageDto; +import kimjang.toolkit.solsol.domain.user.dto.UserDto; +import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/room/ChatRoomListTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/room/ChatRoomListTest.java index 9a33dcf..0333a97 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/room/ChatRoomListTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/room/ChatRoomListTest.java @@ -1,7 +1,7 @@ package kimjang.toolkit.solsol.room; -import kimjang.toolkit.solsol.room.dto.ChatRoomDto; -import kimjang.toolkit.solsol.room.service.ChatRoomService; +import kimjang.toolkit.solsol.domain.room.dto.ChatRoomDto; +import kimjang.toolkit.solsol.domain.room.service.ChatRoomService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/room/CreateRoomTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/room/CreateRoomTest.java index 3bd5dc8..5b63bee 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/room/CreateRoomTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/room/CreateRoomTest.java @@ -1,13 +1,10 @@ package kimjang.toolkit.solsol.room; -import kimjang.toolkit.solsol.room.dto.InviteChatRoomDto; -import kimjang.toolkit.solsol.user.dto.UserDto; -import kimjang.toolkit.solsol.room.entity.ChatRoom; -import kimjang.toolkit.solsol.room.entity.ChatRoomCustomerRelationship; -import kimjang.toolkit.solsol.room.dto.CreateChatRoomDto; -import kimjang.toolkit.solsol.room.repository.ChatRoomCustormerRelationshipRepository; -import kimjang.toolkit.solsol.room.repository.ChatRoomRepository; -import kimjang.toolkit.solsol.room.service.ChatRoomService; +import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; +import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomCustormerRelationshipRepository; +import kimjang.toolkit.solsol.domain.room.repository.ChatRoomRepository; +import kimjang.toolkit.solsol.domain.room.service.ChatRoomService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,8 +12,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/user/UniqueEmailTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/user/UniqueEmailTest.java index 5d96b3d..eb16f8b 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/user/UniqueEmailTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/user/UniqueEmailTest.java @@ -1,7 +1,6 @@ package kimjang.toolkit.solsol.user; -import kimjang.toolkit.solsol.user.service.UserService; -import lombok.RequiredArgsConstructor; +import kimjang.toolkit.solsol.domain.user.service.UserService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 57f76c6c26d396dc9688544cc509116062fcf0da Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 13:57:06 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[Feat]=20refresh=20token=20cache=20save?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solsol/domain/cache/RefreshToken.java | 4 +++ .../cache/RefreshTokenCacheService.java | 29 ++++++++++++++++--- .../domain/cache/RefreshTokenRepository.java | 6 +++- .../user/controller/UserController.java | 3 +- .../solsol/domain/user/service/JwtIssuer.java | 12 +++++--- .../domain/user/service/UserService.java | 4 +-- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java index e8d13a4..c6a7a07 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshToken.java @@ -21,4 +21,8 @@ public class RefreshToken { @Column(name = "refresh_token") private String refreshToken; + + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java index ad95b51..cef7ae1 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java @@ -1,18 +1,39 @@ package kimjang.toolkit.solsol.domain.cache; +import kimjang.toolkit.solsol.exception.UnauthorizedException; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; +import java.util.Optional; + @Service @RequiredArgsConstructor public class RefreshTokenCacheService { private final RefreshTokenRepository refreshTokenRepository; - @Cacheable(value = "refresh") - public String findRefreshToken(String email){ - return + /** + * CachePut은 캐시가 있더라도 메서드를 실행한 결과를 Cache에 저장 + * 따라서 무조건 새로운 token을 저장하고 싶은 경우 적절 + * 한 메일에 한 refresh token만 가능! + * + * @param email + * @return + */ + @CachePut(value= "refresh", key="#email") + public RefreshToken saveToken(String email, String refreshToken){ + Optional token = refreshTokenRepository.findByEmail(email); + if(token.isPresent()){ // 예전에 로그인해서 refresh token이 남아 있는 경우 + token.get().setRefreshToken(refreshToken); + return refreshTokenRepository.save(token.get()); + } else{ // 처음 refresh token 만들어서 저장하는 경우 + RefreshToken newToken = RefreshToken.builder() + .email(email) + .refreshToken(refreshToken) + .build(); + return refreshTokenRepository.save(newToken); + } } - } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java index 8efe676..5f3dc36 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenRepository.java @@ -1,7 +1,11 @@ package kimjang.toolkit.solsol.domain.cache; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository -public interface RefreshTokenRepository { +public interface RefreshTokenRepository extends JpaRepository { + Optional findByEmail(String email); } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java index b54dc7f..44df1bc 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/controller/UserController.java @@ -2,7 +2,6 @@ import kimjang.toolkit.solsol.domain.user.dto.*; import kimjang.toolkit.solsol.domain.user.service.FriendService; -import kimjang.toolkit.solsol.user.dto.*; import kimjang.toolkit.solsol.domain.user.service.UserService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -65,7 +64,7 @@ public ResponseEntity getUserDetail(){ } @PostMapping("/refresh-token") - public LoginSuccessDto getAccessTokenByRefreshToken(@RequestBody RefreshDto refreshDto){ + public IssuedTokens getAccessTokenByRefreshToken(@RequestBody RefreshDto refreshDto){ return userService.getAccessToken(refreshDto); } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index ea1d1c9..a4415e1 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -8,8 +8,8 @@ import io.jsonwebtoken.security.SignatureException; import kimjang.toolkit.solsol.config.jwt.JwtInvalidException; import kimjang.toolkit.solsol.config.jwt.SecurityConstants; +import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; import kimjang.toolkit.solsol.domain.user.dto.IssuedTokens; -import kimjang.toolkit.solsol.domain.user.dto.LoginSuccessDto; import kimjang.toolkit.solsol.domain.user.dto.RefreshDto; import kimjang.toolkit.solsol.domain.user.entities.Authority; import lombok.extern.slf4j.Slf4j; @@ -32,10 +32,14 @@ public class JwtIssuer { private final Long ONE_MINUTE = 60 * ONE_SECONDS; private final long accessExpireMin; private final long refreshExpireMin; + private final RefreshTokenCacheService refreshTokenCacheService; + public JwtIssuer(@Value("${jwt.access-expire-min:10}") long accessExpireMin, - @Value("${jwt.refresh-expire-min:60}") long refreshExpireMin){ + @Value("${jwt.refresh-expire-min:60}") long refreshExpireMin, + RefreshTokenCacheService refreshTokenCacheService){ this.accessExpireMin = accessExpireMin; this.refreshExpireMin = refreshExpireMin; + this.refreshTokenCacheService = refreshTokenCacheService; } private String getToken(String email, String authorities, Long expireTime) { @@ -67,7 +71,7 @@ public String getRefreshToken(String email, String authorities) { return getToken(email, authorities, refreshExpireMin*ONE_MINUTE); } - public LoginSuccessDto getAccessTokenByRefreshToken(RefreshDto refreshDto) { + public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { try { Claims claims = Jwts.parser() .verifyWith(key) // 서버가 저장하고 있는 키로 payload 암호 풀기 @@ -79,7 +83,7 @@ public LoginSuccessDto getAccessTokenByRefreshToken(RefreshDto refreshDto) { String accessToken = getAccessToken(email, authorities); String refreshToken = getRefreshToken(email, authorities); - return LoginSuccessDto.builder() + return IssuedTokens.builder() .accessToken(accessToken) .refreshToken(refreshToken) .build(); diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java index 19b1cec..5f36e5f 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java @@ -4,7 +4,6 @@ import kimjang.toolkit.solsol.domain.user.dto.*; import kimjang.toolkit.solsol.exception.UnauthorizedException; import kimjang.toolkit.solsol.domain.user.entities.User; -import kimjang.toolkit.solsol.user.dto.*; import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,7 +24,6 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final JwtIssuer jwtIssuer; - private final RefreshTokenCacheService refreshTokenCacheService; @Transactional public UserDto registerUser(CreateUserDto createUserDto){ @@ -82,7 +80,7 @@ public LoginSuccessDto userLoginAndSaveRefreshToken(LoginDto loginDto){ * @param refreshDto * @return */ - public LoginSuccessDto getAccessToken(RefreshDto refreshDto) { + public IssuedTokens getAccessToken(RefreshDto refreshDto) { /** * 캐시나 DB에 존재하는 refresh token인지 확인 * - 없으면 401 에러 From 83ea565b3a2a228842cbd4dc5cd7f454ff216d7b Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 14:59:38 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[Fix]=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EC=97=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../toolkit/solsol/config/SecurityConfig.java | 3 - .../cache/RefreshTokenCacheService.java | 20 ++- .../message/repository/ChatRepository.java | 4 +- .../domain/room/ChatRoomController.java | 1 - .../room/repository/ChatRoomRepository.java | 2 +- .../solsol/domain/user/dto/AuthorityInfo.java | 15 +++ .../user/reposiotry/FriendRepository.java | 2 +- .../user/reposiotry/UserRepository.java | 2 +- .../solsol/domain/user/service/JwtIssuer.java | 114 ++++++++++-------- .../domain/user/service/UserService.java | 20 ++- 10 files changed, 115 insertions(+), 68 deletions(-) create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AuthorityInfo.java diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java index bdf4c42..1556487 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java @@ -2,13 +2,10 @@ import kimjang.toolkit.solsol.config.filter.*; import kimjang.toolkit.solsol.config.provider.JwtAuthenticationProvider; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java index cef7ae1..700904e 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java @@ -20,20 +20,32 @@ public class RefreshTokenCacheService { * 한 메일에 한 refresh token만 가능! * * @param email + * @param hashedRefreshToken : hashing된 refresh token * @return */ @CachePut(value= "refresh", key="#email") - public RefreshToken saveToken(String email, String refreshToken){ + public RefreshToken saveToken(String email, String hashedRefreshToken){ Optional token = refreshTokenRepository.findByEmail(email); - if(token.isPresent()){ // 예전에 로그인해서 refresh token이 남아 있는 경우 - token.get().setRefreshToken(refreshToken); + if(token.isPresent()){ // 예전에 로그인해서 refresh token이 남아 있는 경우 업데이트 + token.get().setRefreshToken(hashedRefreshToken); return refreshTokenRepository.save(token.get()); } else{ // 처음 refresh token 만들어서 저장하는 경우 RefreshToken newToken = RefreshToken.builder() .email(email) - .refreshToken(refreshToken) + .refreshToken(hashedRefreshToken) .build(); return refreshTokenRepository.save(newToken); } } + + /** + * 재발급 용도로 저장된 token 검색 + * @param email + * @return + */ + @Cacheable(value= "refresh") + public RefreshToken searchToken(String email){ + return refreshTokenRepository.findByEmail(email) + .orElseThrow(()-> new UnauthorizedException("인증되지 않았습니다. 다시 시도해주세요.")); + } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java index 9a81ee4..73ed57e 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/message/repository/ChatRepository.java @@ -28,7 +28,7 @@ public interface ChatRepository extends JpaRepository { * @Param roomExitTime : 사용자가 최근 방에서 나간 시간 */ @Query(value="SELECT " + - " new kimjang.toolkit.solsol.message.dto.SendChatMessageDto(" + + " new kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto(" + " :roomId, cm.content, cm.createDate, u.id, u.email, u.name )" + // 채팅 내용 " FROM ChatMessage cm " + // 채팅 " join User u ON u.id = cm.user.id " + // 유저 @@ -45,7 +45,7 @@ public interface ChatRepository extends JpaRepository { // 유저가 속한 채팅방에 가장 최근 채팅만 쿼리 @Query(value="SELECT " + - " new kimjang.toolkit.solsol.message.dto.SendChatMessageDto(" + + " new kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto(" + " :roomId, cm.content, cm.createDate, u.id, u.email, u.name )" + // 채팅 내용 " FROM ChatMessage cm " + // 채팅 " join User u ON u.id = cm.user.id " + // 유저 diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java index 94ee5dc..1950aa7 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/ChatRoomController.java @@ -4,7 +4,6 @@ import kimjang.toolkit.solsol.domain.room.dto.CreateChatRoomDto; import kimjang.toolkit.solsol.domain.room.dto.InviteChatRoomDto; import kimjang.toolkit.solsol.domain.room.dto.LeaveRoomDto; -import kimjang.toolkit.solsol.room.dto.*; import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto; import kimjang.toolkit.solsol.domain.room.service.ChatRoomService; import kimjang.toolkit.solsol.domain.room.service.ChatRoomStompService; diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java index 38fb188..2ac7249 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/room/repository/ChatRoomRepository.java @@ -10,7 +10,7 @@ public interface ChatRoomRepository extends JpaRepository { - @Query("SELECT new kimjang.toolkit.solsol.room.dto.ChatRoomDto( " + + @Query("SELECT new kimjang.toolkit.solsol.domain.room.dto.ChatRoomDto( " + " cr.id, ccr.roomName, cr.memberCnt, ccr.roomExitTime, " + " (SELECT cm.content FROM ChatMessage cm WHERE cm.chatRoom.id = cr.id AND " + // 채팅 내용 가져오기 " cm.createDate =(SELECT MAX(ccm.createDate) FROM ChatMessage ccm WHERE ccm.chatRoom.id = cm.chatRoom.id)) " + // 채팅방에서 가장 최근 채팅 날짜 diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AuthorityInfo.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AuthorityInfo.java new file mode 100644 index 0000000..58596ca --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/AuthorityInfo.java @@ -0,0 +1,15 @@ +package kimjang.toolkit.solsol.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuthorityInfo { + private String email; + private String authorities; +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java index dce3e29..246421c 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/FriendRepository.java @@ -10,7 +10,7 @@ public interface FriendRepository extends JpaRepository { - @Query(value = "SELECT distinct new kimjang.toolkit.solsol.user.dto.UserProfileDto( " + + @Query(value = "SELECT distinct new kimjang.toolkit.solsol.domain.user.dto.UserProfileDto( " + " f.subUser.id, f.subUser.email, f.subUser.name, f.subUser.imgUrl ) FROM Friend f " + " JOIN User u ON f.user = u" + " WHERE u.email = :email") // 이메일이 email인 유저가 main인 f만 존재~ diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java index b11eb77..612d03f 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/reposiotry/UserRepository.java @@ -15,7 +15,7 @@ public interface UserRepository extends JpaRepository { @Query(value = "select u from User u join FETCH u.authorities a WHERE u.email = :email") Optional findByEmail(@Param("email") String email); - @Query(value = "select new kimjang.toolkit.solsol.user.dto.UserProfileDto(" + + @Query(value = "select new kimjang.toolkit.solsol.domain.user.dto.UserProfileDto(" + " u.id, u.email, u.name, u.imgUrl ) from User u WHERE u.email = :email") UserProfileDto findProfileByEmail(@Param("email") String email); diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index a4415e1..7cb0f5e 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -8,12 +8,16 @@ import io.jsonwebtoken.security.SignatureException; import kimjang.toolkit.solsol.config.jwt.JwtInvalidException; import kimjang.toolkit.solsol.config.jwt.SecurityConstants; +import kimjang.toolkit.solsol.domain.cache.RefreshToken; import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; +import kimjang.toolkit.solsol.domain.user.dto.AuthorityInfo; import kimjang.toolkit.solsol.domain.user.dto.IssuedTokens; import kimjang.toolkit.solsol.domain.user.dto.RefreshDto; import kimjang.toolkit.solsol.domain.user.entities.Authority; +import kimjang.toolkit.solsol.exception.UnauthorizedException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; @@ -21,7 +25,6 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; -import java.util.HashSet; import java.util.Set; @Slf4j @@ -33,60 +36,27 @@ public class JwtIssuer { private final long accessExpireMin; private final long refreshExpireMin; private final RefreshTokenCacheService refreshTokenCacheService; + private final PasswordEncoder passwordEncoder; public JwtIssuer(@Value("${jwt.access-expire-min:10}") long accessExpireMin, @Value("${jwt.refresh-expire-min:60}") long refreshExpireMin, - RefreshTokenCacheService refreshTokenCacheService){ + RefreshTokenCacheService refreshTokenCacheService, + PasswordEncoder passwordEncoder){ this.accessExpireMin = accessExpireMin; this.refreshExpireMin = refreshExpireMin; this.refreshTokenCacheService = refreshTokenCacheService; - } - - private String getToken(String email, String authorities, Long expireTime) { - log.info("authories : {}",authorities); - long now = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - return Jwts.builder().issuer("Sol-Kimjang").subject("JWT Token") - // 비밀번호는 절대 안된다. - .claim("email", email) - .claim("authorities", authorities) - .issuedAt(new Date(now)) - // 만료시간, ms 단위, 만료 시간을 넘어선 토큰이 들어오면 만료됐다고 예외가 발생한다. - .expiration(new Date(now + expireTime)) - // 디지털 서명 작성 - .signWith(key).compact(); - } - - public String getAccessToken(String email, Set authorities) { - log.info("유통기한 : {}",accessExpireMin*ONE_MINUTE); - return getToken(email, populateAuthorities(authorities), accessExpireMin*ONE_MINUTE); - } - public String getRefreshToken(String email, Set authorities) { - return getToken(email, populateAuthorities(authorities), refreshExpireMin*ONE_MINUTE); - } - public String getAccessToken(String email, String authorities) { - log.info("유통기한 : {}",accessExpireMin*ONE_MINUTE); - return getToken(email, authorities, accessExpireMin*ONE_MINUTE); - } - public String getRefreshToken(String email, String authorities) { - return getToken(email, authorities, refreshExpireMin*ONE_MINUTE); + this.passwordEncoder = passwordEncoder; } public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { try { - Claims claims = Jwts.parser() - .verifyWith(key) // 서버가 저장하고 있는 키로 payload 암호 풀기 - .build() - .parseSignedClaims(refreshDto.getRefreshToken()) - .getPayload(); - String email = (String) claims.get("email"); - String authorities = (String) claims.get("authorities"); + AuthorityInfo authorityInfo = getAuthorityInfo(refreshDto); + RefreshToken savedRefreshToken = refreshTokenCacheService.searchToken(authorityInfo.getEmail()); + // 저장된 refresh token과 같은지 확인 같을 때 재발급 가능! + hashMatchingTokens(savedRefreshToken.getRefreshToken(), refreshDto.getRefreshToken()); + + return getAccessTokenByAuthorityInfo(authorityInfo); - String accessToken = getAccessToken(email, authorities); - String refreshToken = getRefreshToken(email, authorities); - return IssuedTokens.builder() - .accessToken(accessToken) - .refreshToken(refreshToken) - .build(); } catch (SignatureException signatureException) { throw new JwtInvalidException("signature key is different", signatureException); } catch (ExpiredJwtException expiredJwtException) { @@ -96,23 +66,61 @@ public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { } catch (IllegalArgumentException illegalArgumentException) { throw new JwtInvalidException("using illegal argument like null", illegalArgumentException); } - } - private String populateAuthorities(Set collection) { - Set authoritiesSet = new HashSet<>(); - for (Authority authority : collection) { - authoritiesSet.add(authority.getName()); + private void hashMatchingTokens(String savedRefreshToken, String refreshToken){ + if(!passwordEncoder.matches(refreshToken, savedRefreshToken)){ + throw new UnauthorizedException("refresh token is not match"); } - return String.join(",", authoritiesSet); } - public IssuedTokens getAccessTokenByUserInfo(String email, Set authorities) { - String accessToken = getAccessToken(email, authorities); - String refreshToken = getRefreshToken(email, authorities); + private AuthorityInfo getAuthorityInfo(RefreshDto refreshDto) { + Claims claims = Jwts.parser() + .verifyWith(key) // 서버가 저장하고 있는 키로 payload 암호 풀기 + .build() + .parseSignedClaims(refreshDto.getRefreshToken()) + .getPayload(); + String email = (String) claims.get("email"); + String authorities = (String) claims.get("authorities"); + + return AuthorityInfo.builder() + .email(email) + .authorities(authorities).build(); + } + + public IssuedTokens getAccessTokenByAuthorityInfo(AuthorityInfo authorityInfo) { + String accessToken = getAccessToken(authorityInfo); + String refreshToken = getRefreshToken(authorityInfo); return IssuedTokens.builder() .accessToken(accessToken) .refreshToken(refreshToken) .build(); } + + public String getAccessToken(AuthorityInfo authorityInfo) { + log.info("유통기한 : {}",accessExpireMin*ONE_MINUTE); + return getToken(authorityInfo.getEmail(), authorityInfo.getAuthorities(), accessExpireMin*ONE_MINUTE); + } + public String getRefreshToken(AuthorityInfo authorityInfo) { + return getToken(authorityInfo.getEmail(), authorityInfo.getAuthorities(), refreshExpireMin*ONE_MINUTE); + } + + private String getToken(String email, String authorities, Long expireTime) { + log.info("authories : {}",authorities); + long now = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + return Jwts.builder().issuer("Sol-Kimjang").subject("JWT Token") + // 비밀번호는 절대 안된다. + .claim("email", email) + .claim("authorities", authorities) + .issuedAt(new Date(now)) + // 만료시간, ms 단위, 만료 시간을 넘어선 토큰이 들어오면 만료됐다고 예외가 발생한다. + .expiration(new Date(now + expireTime)) + // 디지털 서명 작성 + .signWith(key).compact(); + } + + public void saveIssuedToken(String email, String refreshToken) { + String hashedRefreshToken = passwordEncoder.encode(refreshToken); + refreshTokenCacheService.saveToken(email, hashedRefreshToken); + } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java index 5f36e5f..666be81 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/UserService.java @@ -1,7 +1,7 @@ package kimjang.toolkit.solsol.domain.user.service; -import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; import kimjang.toolkit.solsol.domain.user.dto.*; +import kimjang.toolkit.solsol.domain.user.entities.Authority; import kimjang.toolkit.solsol.exception.UnauthorizedException; import kimjang.toolkit.solsol.domain.user.entities.User; import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository; @@ -15,7 +15,9 @@ import org.springframework.transaction.annotation.Transactional; import javax.naming.AuthenticationException; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; @Slf4j @Service @@ -61,7 +63,13 @@ public LoginSuccessDto userLoginAndSaveRefreshToken(LoginDto loginDto){ throw new BadCredentialsException("bad credential: using unmatched password"); } log.info("email : "+loginDto.getEmail()); - IssuedTokens tokens = jwtIssuer.getAccessTokenByUserInfo(user.getEmail(), user.getAuthorities()); + String authorities = populateAuthorities(user.getAuthorities()); + AuthorityInfo authorityInfo = AuthorityInfo.builder().email(user.getEmail()) + .authorities(authorities).build(); + // 새로운 tokens 재발급 + IssuedTokens tokens = jwtIssuer.getAccessTokenByAuthorityInfo(authorityInfo); + // 재발급한 tokens Cache와 DB에 저장 + jwtIssuer.saveIssuedToken(user.getEmail(), tokens.getRefreshToken()); return LoginSuccessDto.builder() .id(user.getId()) .email(user.getEmail()) @@ -100,4 +108,12 @@ public UserProfileDto getUserDetail() { } return userRepository.findProfileByEmail(userEmail); } + + private String populateAuthorities(Set collection) { + Set authoritiesSet = new HashSet<>(); + for (Authority authority : collection) { + authoritiesSet.add(authority.getName()); + } + return String.join(",", authoritiesSet); + } } From 2aa00f74d009bea6a58ad57119c332d00a1aeb2b Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 15:12:58 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[Feat]=20issue=EB=90=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=EC=9D=84=20caching=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Backend/pom.xml | 20 +++-- .../solsol/config/cache/CacheConfig.java | 79 +++++++++++++++++++ .../main/resources/application-dev.properties | 7 +- .../toolkit/solsol/jwt/IssueCachingTest.java | 4 + 4 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/config/cache/CacheConfig.java create mode 100644 Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java diff --git a/Backend/pom.xml b/Backend/pom.xml index 4b5c744..f3561a3 100644 --- a/Backend/pom.xml +++ b/Backend/pom.xml @@ -115,14 +115,22 @@ 2.5 provided - - - io.sixhours - memcached-spring-boot-starter - 2.5.0 + com.google.code.simple-spring-memcached + spring-cache + 4.1.3 + + + com.google.code.simple-spring-memcached + simple-spring-memcached + 4.1.3 + + + + com.google.code.simple-spring-memcached + xmemcached-provider + 4.1.3 - diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/CacheConfig.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/CacheConfig.java new file mode 100644 index 0000000..dc48c49 --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/CacheConfig.java @@ -0,0 +1,79 @@ +package kimjang.toolkit.solsol.config.cache; + +import com.google.code.ssm.Cache; +import com.google.code.ssm.CacheFactory; +import com.google.code.ssm.config.AddressProvider; +import com.google.code.ssm.config.DefaultAddressProvider; +import com.google.code.ssm.providers.CacheConfiguration; +import com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl; +import com.google.code.ssm.spring.ExtendedSSMCacheManager; +import com.google.code.ssm.spring.SSMCache; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; + +@Slf4j +@Configuration +public class CacheConfig extends CachingConfigurerSupport { + + @Value("${spring.cache.address}") + private String address; + + @Value("${spring.cache.operationTimeout}") + private String operationTimeout; + + @Value("${spring.cache.cacheName}") + private String cacheName; + + @Value("${spring.cache.expiration}") + private String expiration; + + @Bean + public CacheManager cacheManager() { + + CacheFactory cacheFactory = getCacheFactory(); + + Cache object = null; + + try { + object = cacheFactory.getObject(); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + SSMCache ssmCache = new SSMCache(object, Integer.parseInt(expiration), true); + + ArrayList ssmCaches = new ArrayList<>(); + ssmCaches.add(0, ssmCache); + + ExtendedSSMCacheManager ssmCacheManager = new ExtendedSSMCacheManager(); + ssmCacheManager.setCaches(ssmCaches); + + return ssmCacheManager; + } + + private CacheFactory getCacheFactory() { + CacheConfiguration cacheConfiguration = new CacheConfiguration(); + cacheConfiguration.setConsistentHashing(true); + cacheConfiguration.setUseBinaryProtocol(true); + cacheConfiguration.setOperationTimeout(Integer.getInteger(operationTimeout)); + cacheConfiguration.setUseNameAsKeyPrefix(true); + cacheConfiguration.setKeyPrefixSeparator(":"); + + MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl(); + + AddressProvider addressProvider = new DefaultAddressProvider(address); + + CacheFactory cacheFactory = new CacheFactory(); + cacheFactory.setCacheName(cacheName); + cacheFactory.setCacheClientFactory(cacheClientFactory); + cacheFactory.setAddressProvider(addressProvider); + cacheFactory.setConfiguration(cacheConfiguration); + return cacheFactory; + } +} \ No newline at end of file diff --git a/Backend/src/main/resources/application-dev.properties b/Backend/src/main/resources/application-dev.properties index 19d6f39..ee20bea 100644 --- a/Backend/src/main/resources/application-dev.properties +++ b/Backend/src/main/resources/application-dev.properties @@ -22,6 +22,7 @@ spring.jpa.properties.hibernate.format_sql= true #springdoc.swagger-ui.path=/swagger-ui.html # memcached -memcached.cache.servers: memcached:11211 -memcached.cache.expirations: 3600 -memcached.cache.operation-timeout: 3000 \ No newline at end of file +spring.cache.operationTimeout: 1500 +spring.cache.cacheName: testCache +spring.cache.expiration: 600 +spring.cache.address: localhost:11211 diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java new file mode 100644 index 0000000..005c0aa --- /dev/null +++ b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java @@ -0,0 +1,4 @@ +package kimjang.toolkit.solsol.jwt; + +public class IssueCachingTest { +} From 17745d584e5e706fc4e3c17804c828540cf87a17 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 16:09:24 +0900 Subject: [PATCH 06/10] [Test] Cache save and hit test success --- .../cache/RefreshTokenCacheService.java | 10 ++--- .../solsol/domain/user/service/JwtIssuer.java | 4 +- .../main/resources/application-dev.properties | 2 +- .../toolkit/solsol/jwt/IssueCachingTest.java | 4 -- .../jwt/RefreshTokenCacheServiceTest.java | 40 +++++++++++++++++++ 5 files changed, 48 insertions(+), 12 deletions(-) delete mode 100644 Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java create mode 100644 Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java index 700904e..0df0928 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java @@ -24,17 +24,17 @@ public class RefreshTokenCacheService { * @return */ @CachePut(value= "refresh", key="#email") - public RefreshToken saveToken(String email, String hashedRefreshToken){ + public String saveToken(String email, String hashedRefreshToken){ Optional token = refreshTokenRepository.findByEmail(email); if(token.isPresent()){ // 예전에 로그인해서 refresh token이 남아 있는 경우 업데이트 token.get().setRefreshToken(hashedRefreshToken); - return refreshTokenRepository.save(token.get()); + return refreshTokenRepository.save(token.get()).getRefreshToken(); } else{ // 처음 refresh token 만들어서 저장하는 경우 RefreshToken newToken = RefreshToken.builder() .email(email) .refreshToken(hashedRefreshToken) .build(); - return refreshTokenRepository.save(newToken); + return refreshTokenRepository.save(newToken).getRefreshToken(); } } @@ -44,8 +44,8 @@ public RefreshToken saveToken(String email, String hashedRefreshToken){ * @return */ @Cacheable(value= "refresh") - public RefreshToken searchToken(String email){ + public String searchToken(String email){ return refreshTokenRepository.findByEmail(email) - .orElseThrow(()-> new UnauthorizedException("인증되지 않았습니다. 다시 시도해주세요.")); + .orElseThrow(()-> new UnauthorizedException("인증되지 않았습니다. 다시 시도해주세요.")).getRefreshToken(); } } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index 7cb0f5e..b6bccbd 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -51,9 +51,9 @@ public JwtIssuer(@Value("${jwt.access-expire-min:10}") long accessExpireMin, public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { try { AuthorityInfo authorityInfo = getAuthorityInfo(refreshDto); - RefreshToken savedRefreshToken = refreshTokenCacheService.searchToken(authorityInfo.getEmail()); + String savedRefreshToken = refreshTokenCacheService.searchToken(authorityInfo.getEmail()); // 저장된 refresh token과 같은지 확인 같을 때 재발급 가능! - hashMatchingTokens(savedRefreshToken.getRefreshToken(), refreshDto.getRefreshToken()); + hashMatchingTokens(savedRefreshToken, refreshDto.getRefreshToken()); return getAccessTokenByAuthorityInfo(authorityInfo); diff --git a/Backend/src/main/resources/application-dev.properties b/Backend/src/main/resources/application-dev.properties index ee20bea..a17db5d 100644 --- a/Backend/src/main/resources/application-dev.properties +++ b/Backend/src/main/resources/application-dev.properties @@ -23,6 +23,6 @@ spring.jpa.properties.hibernate.format_sql= true # memcached spring.cache.operationTimeout: 1500 -spring.cache.cacheName: testCache +spring.cache.cacheName: refresh spring.cache.expiration: 600 spring.cache.address: localhost:11211 diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java deleted file mode 100644 index 005c0aa..0000000 --- a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/IssueCachingTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package kimjang.toolkit.solsol.jwt; - -public class IssueCachingTest { -} diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java new file mode 100644 index 0000000..851a209 --- /dev/null +++ b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java @@ -0,0 +1,40 @@ +package kimjang.toolkit.solsol.jwt; + +import kimjang.toolkit.solsol.SolsolApplication; +import kimjang.toolkit.solsol.domain.cache.RefreshToken; +import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@SpringBootTest(classes = SolsolApplication.class) +@ActiveProfiles(value = "dev") +@Transactional +public class RefreshTokenCacheServiceTest { + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private RefreshTokenCacheService refreshTokenCacheService; + + @Test + public void checkCacheableToken(){ + String email = "solsol@gmail.com"; + String refreshToken = "1234"; + String hashedRefreshToken = passwordEncoder.encode(refreshToken); + + // email에 맞는 refresh token 캐시에 저장 + refreshTokenCacheService.saveToken(email, hashedRefreshToken); + // 캐시에 있는 refresh token 얻어오기 + String savedRefreshToken = refreshTokenCacheService.searchToken(email); + Assertions.assertTrue(passwordEncoder.matches(refreshToken, savedRefreshToken)); + } +} From 24d56bcb4d92f381c532de19c607eed80c89bf75 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Thu, 1 Aug 2024 17:12:22 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[Test]=20DB=EC=99=80=20=EC=BA=90=EC=8B=9C?= =?UTF-8?q?=20=EB=B9=84=EA=B5=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20table=20=ED=81=AC=EA=B8=B0=EA=B0=80=20=EC=BB=A4?= =?UTF-8?q?=EC=A0=B8=EB=8F=84=20=EC=BA=90=EC=8B=9C=EC=9D=98=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9D=B4=20=EC=A4=84=EC=96=B4=EB=93=A4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/application-dev.properties | 6 +- .../jwt/RefreshTokenCacheServiceTest.java | 84 ++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/Backend/src/main/resources/application-dev.properties b/Backend/src/main/resources/application-dev.properties index a17db5d..7497618 100644 --- a/Backend/src/main/resources/application-dev.properties +++ b/Backend/src/main/resources/application-dev.properties @@ -15,8 +15,8 @@ spring.datasource.username=root spring.datasource.password=sol-root spring.jpa.hibernate.ddl-auto= update spring.datasource.url=jdbc:mysql://localhost:3306/chat -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql= true +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.format_sql= false # swagger #springdoc.swagger-ui.path=/swagger-ui.html @@ -26,3 +26,5 @@ spring.cache.operationTimeout: 1500 spring.cache.cacheName: refresh spring.cache.expiration: 600 spring.cache.address: localhost:11211 +logging.level.org.springframework.cache=ERROR +logging.level.com.google.code.ssm.spring.SSMCache=ERROR diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java index 851a209..5ea8629 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/RefreshTokenCacheServiceTest.java @@ -3,7 +3,7 @@ import kimjang.toolkit.solsol.SolsolApplication; import kimjang.toolkit.solsol.domain.cache.RefreshToken; import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; -import lombok.RequiredArgsConstructor; +import kimjang.toolkit.solsol.domain.cache.RefreshTokenRepository; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -13,10 +13,12 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; +import java.time.LocalDateTime; + @Slf4j @SpringBootTest(classes = SolsolApplication.class) @ActiveProfiles(value = "dev") -@Transactional public class RefreshTokenCacheServiceTest { @Autowired @@ -25,6 +27,9 @@ public class RefreshTokenCacheServiceTest { @Autowired private RefreshTokenCacheService refreshTokenCacheService; + @Autowired + private RefreshTokenRepository refreshTokenRepository; + @Test public void checkCacheableToken(){ String email = "solsol@gmail.com"; @@ -37,4 +42,79 @@ public void checkCacheableToken(){ String savedRefreshToken = refreshTokenCacheService.searchToken(email); Assertions.assertTrue(passwordEncoder.matches(refreshToken, savedRefreshToken)); } + + + + private final int testCount = 10000; + @Test + public void countTimeDBAndCache(){ + // set up + String email = "solsol@gmail.com"; + String refreshToken = "1234"; + String hashedRefreshToken = passwordEncoder.encode(refreshToken); + RefreshToken tokenEntity = RefreshToken.builder() + .email(email) + .refreshToken(hashedRefreshToken) + .build(); + refreshTokenRepository.save(tokenEntity); + // email에 맞는 refresh token 캐시에 저장 + refreshTokenCacheService.saveToken(email, hashedRefreshToken); + + LocalDateTime start = LocalDateTime.now(); + for(int i=0; i Date: Fri, 2 Aug 2024 18:04:31 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[Test]=20refresh=20token=20=EC=9E=AC?= =?UTF-8?q?=ED=99=9C=EC=9A=A9=20=EB=B0=A9=EC=A7=80=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../toolkit/solsol/config/SecurityConfig.java | 4 - .../solsol/config/cache/TokenHasher.java | 27 ++++ .../cache/RefreshTokenCacheService.java | 4 + .../solsol/domain/user/dto/RefreshDto.java | 4 + .../solsol/domain/user/service/JwtIssuer.java | 35 +++-- .../main/resources/application-dev.properties | 2 - .../toolkit/solsol/jwt/ReIssueTokenTest.java | 122 ++++++++++++++++++ 7 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 Backend/src/main/java/kimjang/toolkit/solsol/config/cache/TokenHasher.java create mode 100644 Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java index 1556487..c5e2a68 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/SecurityConfig.java @@ -149,8 +149,4 @@ public PasswordEncoder passwordEncoder(){ // BCrypt 알고리즘을 이용해서 비밀번호를 해싱하자 return new BCryptPasswordEncoder(); } - - - - } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/TokenHasher.java b/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/TokenHasher.java new file mode 100644 index 0000000..18e64ac --- /dev/null +++ b/Backend/src/main/java/kimjang/toolkit/solsol/config/cache/TokenHasher.java @@ -0,0 +1,27 @@ +package kimjang.toolkit.solsol.config.cache; + +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +@Component +public class TokenHasher{ + public String encode(String token){ + MessageDigest digest = null; + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + byte[] encodedhash = digest.digest(token.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(encodedhash); + } + + public boolean matches(String rawToken, String hashedToken) { + String hashedRawToken = encode(rawToken); + return hashedRawToken.equals(hashedToken); + } +} diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java index 0df0928..77a0be4 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/cache/RefreshTokenCacheService.java @@ -2,6 +2,7 @@ import kimjang.toolkit.solsol.exception.UnauthorizedException; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -38,6 +39,9 @@ public String saveToken(String email, String hashedRefreshToken){ } } + @CacheEvict(value = "refresh", key = "#email") + public void deleteCache(String email){} + /** * 재발급 용도로 저장된 token 검색 * @param email diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java index 553e115..0c819dc 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/dto/RefreshDto.java @@ -1,8 +1,12 @@ package kimjang.toolkit.solsol.domain.user.dto; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter +@NoArgsConstructor +@AllArgsConstructor public class RefreshDto { private String refreshToken; } diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index b6bccbd..93d75a4 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -6,6 +6,7 @@ import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SignatureException; +import kimjang.toolkit.solsol.config.cache.TokenHasher; import kimjang.toolkit.solsol.config.jwt.JwtInvalidException; import kimjang.toolkit.solsol.config.jwt.SecurityConstants; import kimjang.toolkit.solsol.domain.cache.RefreshToken; @@ -36,26 +37,40 @@ public class JwtIssuer { private final long accessExpireMin; private final long refreshExpireMin; private final RefreshTokenCacheService refreshTokenCacheService; - private final PasswordEncoder passwordEncoder; + private final TokenHasher tokenHasher; public JwtIssuer(@Value("${jwt.access-expire-min:10}") long accessExpireMin, @Value("${jwt.refresh-expire-min:60}") long refreshExpireMin, RefreshTokenCacheService refreshTokenCacheService, - PasswordEncoder passwordEncoder){ + TokenHasher tokenHasher){ this.accessExpireMin = accessExpireMin; this.refreshExpireMin = refreshExpireMin; this.refreshTokenCacheService = refreshTokenCacheService; - this.passwordEncoder = passwordEncoder; + this.tokenHasher = tokenHasher; } + /** + * refresh token 재발급 시 호출되는 메서드! + * 요청된 refresh token을 바탕으로 email을 찾고 + * 새로운 tokens를 발급하고 캐시와 DB에 저장! + * @param refreshDto + * @return + */ public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { try { AuthorityInfo authorityInfo = getAuthorityInfo(refreshDto); + // cache hit 저장된 토큰 그대로 가져옴 String savedRefreshToken = refreshTokenCacheService.searchToken(authorityInfo.getEmail()); // 저장된 refresh token과 같은지 확인 같을 때 재발급 가능! - hashMatchingTokens(savedRefreshToken, refreshDto.getRefreshToken()); + hashMatchingTokens(refreshDto.getRefreshToken(), savedRefreshToken); - return getAccessTokenByAuthorityInfo(authorityInfo); + // 기존 토큰 제거하기 + refreshTokenCacheService.deleteCache(authorityInfo.getEmail()); + // 새로운 토큰 재발급 + IssuedTokens issuedTokens = getAccessTokenByAuthorityInfo(authorityInfo); + // 새로운 토큰 저장하기 + saveIssuedToken(authorityInfo.getEmail(), issuedTokens.getRefreshToken()); + return issuedTokens; } catch (SignatureException signatureException) { throw new JwtInvalidException("signature key is different", signatureException); @@ -68,10 +83,12 @@ public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { } } - private void hashMatchingTokens(String savedRefreshToken, String refreshToken){ - if(!passwordEncoder.matches(refreshToken, savedRefreshToken)){ + private void hashMatchingTokens(String refreshToken, String savedRefreshToken){ + // hash match check + if(!tokenHasher.matches(refreshToken, savedRefreshToken)){ throw new UnauthorizedException("refresh token is not match"); } + log.info("존재하는 token과 같은 token을 가지고 있습니다."); } private AuthorityInfo getAuthorityInfo(RefreshDto refreshDto) { @@ -106,12 +123,12 @@ public String getRefreshToken(AuthorityInfo authorityInfo) { } private String getToken(String email, String authorities, Long expireTime) { - log.info("authories : {}",authorities); long now = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); return Jwts.builder().issuer("Sol-Kimjang").subject("JWT Token") // 비밀번호는 절대 안된다. .claim("email", email) .claim("authorities", authorities) + .claim("create_date", LocalDateTime.now().toString()) // 생성 시간을 둬서 여러번 생성되는 것을 방지하기 .issuedAt(new Date(now)) // 만료시간, ms 단위, 만료 시간을 넘어선 토큰이 들어오면 만료됐다고 예외가 발생한다. .expiration(new Date(now + expireTime)) @@ -120,7 +137,7 @@ private String getToken(String email, String authorities, Long expireTime) { } public void saveIssuedToken(String email, String refreshToken) { - String hashedRefreshToken = passwordEncoder.encode(refreshToken); + String hashedRefreshToken = tokenHasher.encode(refreshToken); refreshTokenCacheService.saveToken(email, hashedRefreshToken); } } diff --git a/Backend/src/main/resources/application-dev.properties b/Backend/src/main/resources/application-dev.properties index 7497618..8e925ae 100644 --- a/Backend/src/main/resources/application-dev.properties +++ b/Backend/src/main/resources/application-dev.properties @@ -26,5 +26,3 @@ spring.cache.operationTimeout: 1500 spring.cache.cacheName: refresh spring.cache.expiration: 600 spring.cache.address: localhost:11211 -logging.level.org.springframework.cache=ERROR -logging.level.com.google.code.ssm.spring.SSMCache=ERROR diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java new file mode 100644 index 0000000..db272d1 --- /dev/null +++ b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java @@ -0,0 +1,122 @@ +package kimjang.toolkit.solsol.jwt; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import kimjang.toolkit.solsol.config.cache.TokenHasher; +import kimjang.toolkit.solsol.config.jwt.SecurityConstants; +import kimjang.toolkit.solsol.domain.cache.RefreshTokenCacheService; +import kimjang.toolkit.solsol.domain.user.dto.AuthorityInfo; +import kimjang.toolkit.solsol.domain.user.dto.IssuedTokens; +import kimjang.toolkit.solsol.domain.user.dto.RefreshDto; +import kimjang.toolkit.solsol.domain.user.service.JwtIssuer; +import kimjang.toolkit.solsol.exception.UnauthorizedException; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.transaction.annotation.Transactional; + +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; + +@Slf4j +@SpringBootTest +@Transactional +public class ReIssueTokenTest { + private final SecretKey key = Keys.hmacShaKeyFor(SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8)); + @Autowired + private TokenHasher tokenHasher; + + @Autowired + private RefreshTokenCacheService refreshTokenCacheService; + + @Autowired + private JwtIssuer jwtIssuer; + + + private IssuedTokens issuedTokens; + private final String email = "solsol@gmail.com"; + private final AuthorityInfo authorityInfo1 = AuthorityInfo.builder() + .email(email).authorities("ROLE_USER").build(); + private final AuthorityInfo authorityInfo2 = AuthorityInfo.builder() + .email("email").authorities("ROLE_USER").build(); + + @Test + public void when_reissue_then_not_equal_made_time(){ + // 토큰 생성 + issuedTokens = jwtIssuer.getAccessTokenByAuthorityInfo(authorityInfo1); + // 토큰 저장 + jwtIssuer.saveIssuedToken(email, issuedTokens.getRefreshToken()); + String time1 = getCreatedTime(issuedTokens.getRefreshToken()); + log.info("초기 refresh token 생성 시간 : {}",time1); + // 처음 생성 + IssuedTokens newIssuedTokens = jwtIssuer.getAccessTokenByRefreshToken(new RefreshDto(issuedTokens.getRefreshToken())); + String time2 = getCreatedTime(newIssuedTokens.getRefreshToken()); + log.info("다음 refresh token 생성 시간 : {}",time2); + Assertions.assertNotEquals(time1, time2); + } + + @Test + public void when_reissue_then_not_match(){ + // 토큰 생성 + issuedTokens = jwtIssuer.getAccessTokenByAuthorityInfo(authorityInfo1); + // 토큰 저장 + jwtIssuer.saveIssuedToken(email, issuedTokens.getRefreshToken()); + log.info("초기 토큰 : {}", issuedTokens.getRefreshToken()); + // 해싱된 refresh token 불러오기 + String savedRefreshToken = refreshTokenCacheService.searchToken(authorityInfo1.getEmail()); + + String time1 = getCreatedTime(issuedTokens.getRefreshToken()); + log.info("초기 refresh token 생성 시간 : {}",time1); + // 처음 생성 + IssuedTokens newIssuedTokens = jwtIssuer.getAccessTokenByRefreshToken(new RefreshDto(issuedTokens.getRefreshToken())); + String time2 = getCreatedTime(newIssuedTokens.getRefreshToken()); + log.info("다음 토큰 : {}", newIssuedTokens.getRefreshToken()); + log.info("다음 refresh token 생성 시간 : {}",time2); + + Assertions.assertNotEquals(time1, time2); + // 새로운 refresh token 가져오고, 해싱된 토큰 비교. 다른 값을 해싱했기 때문에 match하지 말아야한다. + Assertions.assertTrue(!tokenHasher.matches(newIssuedTokens.getRefreshToken(), savedRefreshToken)); + } + + @Test + public void when_string_then_not_match_sha_256(){ + // 토큰 생성 + String test1 = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTb2wtS2ltamFuZyIsInN1YiI6IkpXVCBUb2tlbiIsImVtYWlsIjoic29sc29sQGdtYWlsLmNvbSIsImF1dGhvcml0aWVzIjoiUk9MRV9VU0VSIiwiY3JlYXRlX2RhdGUiOiIyMDI0LTA4LTAyVDE3OjMxOjQxLjMzMzkwNCIsImlhdCI6MTcyMjU4NzUwMSwiZXhwIjoxNzIyNTg3NjIxfQ.RYVguGifzq4jQ4fCHfNGTGfFlMLn-VnmMy_BAKPLsEE"; + String test2 = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTb2wtS2ltamFuZyIsInN1YiI6IkpXVCBUb2tlbiIsImVtYWlsIjoic29sc29sQGdtYWlsLmNvbSIsImF1dGhvcml0aWVzIjoiUk9MRV9VU0VSIiwiY3JlYXRlX2RhdGUiOiIyMDI0LTA4LTAyVDE3OjMxOjQxLjcwMDE3MyIsImlhdCI6MTcyMjU4NzUwMSwiZXhwIjoxNzIyNTg3NjIxfQ.J_HxlIgceLJTjbU58_KIgfeb8gRiOfmHPBaWnQyXc7w"; + + String hashed = tokenHasher.encode(test1); + // 새로운 refresh token 가져오고, 해싱된 토큰 비교. 다른 값을 해싱했기 때문에 match하지 말아야한다. + Assertions.assertFalse(tokenHasher.matches(test2, hashed)); + } + + + @Test + public void when_reissue_then_invoke_exception(){ + // 토큰 생성 + issuedTokens = jwtIssuer.getAccessTokenByAuthorityInfo(authorityInfo1); + // 토큰 저장 + jwtIssuer.saveIssuedToken(email, issuedTokens.getRefreshToken()); + String time1 = getCreatedTime(issuedTokens.getRefreshToken()); + log.info("초기 refresh token 생성 시간 : {}",time1); + // 처음 생성 + IssuedTokens newIssuedTokens = jwtIssuer.getAccessTokenByRefreshToken(new RefreshDto(issuedTokens.getRefreshToken())); + String time2 = getCreatedTime(newIssuedTokens.getRefreshToken()); + log.info("다음 refresh token 생성 시간 : {}",time2); + + Assertions.assertThrows(UnauthorizedException.class, + () -> jwtIssuer.getAccessTokenByRefreshToken(new RefreshDto(issuedTokens.getRefreshToken()))); + } + + private String getCreatedTime(String refreshToken) { + Claims claims = Jwts.parser() + .verifyWith(key) // 서버가 저장하고 있는 키로 payload 암호 풀기 + .build() + .parseSignedClaims(refreshToken) + .getPayload(); + return (String) claims.get("create_date"); + } +} From d4ff152127e69a436320c43e7f8f712a1abd3851 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Fri, 2 Aug 2024 18:06:34 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[Fix]=20refresh=20token=20=EC=9E=AC?= =?UTF-8?q?=ED=99=9C=EC=9A=A9=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java index 93d75a4..8d252ff 100644 --- a/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java +++ b/Backend/src/main/java/kimjang/toolkit/solsol/domain/user/service/JwtIssuer.java @@ -86,7 +86,7 @@ public IssuedTokens getAccessTokenByRefreshToken(RefreshDto refreshDto) { private void hashMatchingTokens(String refreshToken, String savedRefreshToken){ // hash match check if(!tokenHasher.matches(refreshToken, savedRefreshToken)){ - throw new UnauthorizedException("refresh token is not match"); + throw new UnauthorizedException("refresh token is already used"); } log.info("존재하는 token과 같은 token을 가지고 있습니다."); } From fe397e442c954e3b0101964400572b958510b721 Mon Sep 17 00:00:00 2001 From: ohchansol Date: Fri, 2 Aug 2024 18:45:09 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[feat]=20memcache=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/application-prod.properties | 6 ++++++ .../toolkit/solsol/jwt/ReIssueTokenTest.java | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Backend/src/main/resources/application-prod.properties b/Backend/src/main/resources/application-prod.properties index 97a2fbd..a6235d3 100644 --- a/Backend/src/main/resources/application-prod.properties +++ b/Backend/src/main/resources/application-prod.properties @@ -21,3 +21,9 @@ spring.jpa.show-sql=true ## aws RDS certification spring.datasource.username=chat_rds spring.datasource.password=chat-rds-root + +# memcached +spring.cache.operationTimeout: 1500 +spring.cache.cacheName: refresh +spring.cache.expiration: 600 +spring.cache.address: kimjang-token-cache-cgl9vt.serverless.apn2.cache.amazonaws.com:11212 diff --git a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java index db272d1..589fbff 100644 --- a/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java +++ b/Backend/src/test/java/kimjang/toolkit/solsol/jwt/ReIssueTokenTest.java @@ -36,6 +36,8 @@ public class ReIssueTokenTest { @Autowired private JwtIssuer jwtIssuer; + @Autowired + private PasswordEncoder bCryptPasswordEncoder; private IssuedTokens issuedTokens; private final String email = "solsol@gmail.com"; @@ -93,6 +95,19 @@ public void when_string_then_not_match_sha_256(){ Assertions.assertFalse(tokenHasher.matches(test2, hashed)); } +// @Test +// public void when_string_then_not_match_bCrypt(){ +// // 토큰 생성 +// String test1 = jwtIssuer.getRefreshToken(authorityInfo1); +// log.info("test1 : {}",test1); +// String test2 = jwtIssuer.getRefreshToken(authorityInfo2);; +// log.info("test2 : {}",test2); +// +// String hashed = bCryptPasswordEncoder.encode(test1); +// // 새로운 refresh token 가져오고, 해싱된 토큰 비교. 다른 값을 해싱했기 때문에 match하지 말아야한다. +// Assertions.assertFalse(bCryptPasswordEncoder.matches(test2, hashed)); +// } + @Test public void when_reissue_then_invoke_exception(){