diff --git a/src/main/java/B1G4/bookmark/apiPayload/exception/handler/StompHandler.java b/src/main/java/B1G4/bookmark/apiPayload/exception/handler/StompHandler.java new file mode 100644 index 0000000..2d8ea73 --- /dev/null +++ b/src/main/java/B1G4/bookmark/apiPayload/exception/handler/StompHandler.java @@ -0,0 +1,27 @@ +package B1G4.bookmark.apiPayload.exception.handler; + +import B1G4.bookmark.security.provider.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +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.stereotype.Component; + +import java.util.Objects; + +@Component +@RequiredArgsConstructor +public class StompHandler implements ChannelInterceptor { + private final JwtTokenProvider jwtTokenProvider; + + @Override + public Message preSend(Message message, MessageChannel channel) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + if (StompCommand.CONNECT.equals(accessor.getCommand())) { + jwtTokenProvider.validateToken(Objects.requireNonNull(accessor.getFirstNativeHeader("Authorization")).substring(7)); + } + return message; + } +} \ No newline at end of file diff --git a/src/main/java/B1G4/bookmark/config/WebSocketConfig.java b/src/main/java/B1G4/bookmark/config/WebSocketConfig.java index 38e35f8..356701e 100644 --- a/src/main/java/B1G4/bookmark/config/WebSocketConfig.java +++ b/src/main/java/B1G4/bookmark/config/WebSocketConfig.java @@ -1,5 +1,6 @@ package B1G4.bookmark.config; +import B1G4.bookmark.apiPayload.exception.handler.StompHandler; import B1G4.bookmark.security.provider.JwtTokenProvider; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; @@ -23,7 +24,9 @@ @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + private final StompHandler stompHandler; private final JwtTokenProvider jwtTokenProvider; + @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); // 구독 경로 @@ -49,7 +52,6 @@ public Message preSend(Message message, MessageChannel channel) { StompCommand.SEND.equals(accessor.getCommand())) { String token = accessor.getFirstNativeHeader("Authorization"); - if (Objects.nonNull(token) && token.startsWith("Bearer ")) { token = token.substring(7); // "Bearer " 제거 try { @@ -64,6 +66,5 @@ public Message preSend(Message message, MessageChannel channel) { } }); } - } diff --git a/src/main/java/B1G4/bookmark/security/provider/JwtTokenProvider.java b/src/main/java/B1G4/bookmark/security/provider/JwtTokenProvider.java index 69d8560..59aed76 100644 --- a/src/main/java/B1G4/bookmark/security/provider/JwtTokenProvider.java +++ b/src/main/java/B1G4/bookmark/security/provider/JwtTokenProvider.java @@ -98,4 +98,23 @@ public Authentication getAuthentication(String token) { throw new AuthException(ErrorStatus.AUTH_INVALID_TOKEN); } } + + public void validateToken(String token) { + try { + Jws claims = getClaims(token); + Date expiration = claims.getBody().getExpiration(); + Date now = new Date(); + + if (expiration.before(now)) { + throw new AuthException(ErrorStatus.AUTH_EXPIRED_TOKEN); + } + } catch (ExpiredJwtException e) { + throw new AuthException(ErrorStatus.AUTH_EXPIRED_TOKEN); + } catch (SecurityException + | MalformedJwtException + | UnsupportedJwtException + | IllegalArgumentException e) { + throw new AuthException(ErrorStatus.AUTH_INVALID_TOKEN); + } + } }