Skip to content

Commit a248f65

Browse files
committed
feat:ãJwtHandshakeInterceptor 구현
1 parent 36962e8 commit a248f65

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.back.koreaTravelGuide.common.config.websocket
2+
3+
import com.back.koreaTravelGuide.common.util.JwtUtil
4+
import org.springframework.http.HttpMethod
5+
import org.springframework.http.server.ServerHttpRequest
6+
import org.springframework.http.server.ServerHttpResponse
7+
import org.springframework.stereotype.Component
8+
import org.springframework.web.socket.WebSocketHandler
9+
import org.springframework.web.socket.server.HandshakeInterceptor
10+
import org.springframework.web.util.UriComponentsBuilder
11+
import java.lang.Exception
12+
import java.net.URI
13+
14+
@Component
15+
class JwtHandshakeInterceptor : HandshakeInterceptor {
16+
override fun beforeHandshake(
17+
request: ServerHttpRequest,
18+
response: ServerHttpResponse,
19+
wsHandler: WebSocketHandler,
20+
attributes: MutableMap<String, Any>,
21+
): Boolean {
22+
val uri: URI = request.uri
23+
val method = request.method
24+
25+
// ✅ SockJS 호환을 위한 임시 우회 (브라우저 테스트용)
26+
// - SockJS는 /info 요청을 토큰 없이 보냄
27+
// - 추후 순수 WebSocket 전환 시 제거 예정
28+
if (HttpMethod.OPTIONS == method || uri.path.endsWith("/info")) {
29+
return true
30+
}
31+
32+
val token =
33+
UriComponentsBuilder.fromUri(request.uri)
34+
.build()
35+
.queryParams
36+
.getFirst("token")
37+
?: return false // 토큰 없으면 연결 거부
38+
39+
return if (JwtUtil.validateToken(token)) {
40+
val userId = JwtUtil.getUserIdFromToken(token)
41+
attributes["userId"] = userId
42+
true
43+
} else {
44+
false
45+
}
46+
}
47+
48+
override fun afterHandshake(
49+
request: ServerHttpRequest,
50+
response: ServerHttpResponse,
51+
wsHandler: WebSocketHandler,
52+
exception: Exception?,
53+
) {
54+
}
55+
}

src/main/kotlin/com/back/koreaTravelGuide/common/config/WebSocketConfig.kt renamed to src/main/kotlin/com/back/koreaTravelGuide/common/config/websocket/WebSocketConfig.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.back.koreaTravelGuide.common.config
1+
package com.back.koreaTravelGuide.common.config.websocket
22

33
import org.springframework.context.annotation.Configuration
44
import org.springframework.messaging.simp.config.MessageBrokerRegistry
@@ -8,10 +8,12 @@ import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerCo
88

99
@Configuration
1010
@EnableWebSocketMessageBroker
11-
class WebSocketConfig : WebSocketMessageBrokerConfigurer {
11+
class WebSocketConfig(
12+
private val jwtHandshakeInterceptor: JwtHandshakeInterceptor,
13+
) : WebSocketMessageBrokerConfigurer {
1214
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
1315
registry.addEndpoint("/ws/chat")
14-
.addInterceptors(JwtHandsshakeInterceptor) // JWT 체크
16+
.addInterceptors(JwtHandshakeInterceptor()) // JWT 체크
1517
.setAllowedOrigins("*")
1618
.withSockJS() // 개발 중 호환성
1719
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.back.koreaTravelGuide.common.util
2+
3+
/*
4+
임시 구현: 테스트 용
5+
토큰이 "test-token"이면 유효하다고 간주
6+
완성 후 이 파일은 삭제 또는 대체
7+
*/
8+
object JwtUtil {
9+
fun validateToken(token: String?): Boolean {
10+
// 테스트용: "test-token"이면 통과
11+
return token != null && token == "test-token"
12+
}
13+
14+
fun getUserIdFromToken(token: String): String {
15+
return "user123" // 테스트용 고정 사용자 ID
16+
}
17+
}

0 commit comments

Comments
 (0)