@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class FilterChannelInterceptor implements ChannelInterceptor {
private final JwtUtil jwtUtil;
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
assert headerAccessor != null;
if (headerAccessor.getCommand() == StompCommand.CONNECT) {
String token = headerAccessor.getFirstNativeHeader("Authorization");
if (token != null) {
try {
if (jwtUtil.validateToken(token)) {
String userEmail = jwtUtil.getUserEmailFromToken(token);
headerAccessor.addNativeHeader("User", userEmail);
}
} catch (BaseException e) {
log.error("토큰 검증 중 오류 발생: {}", e.getMessage());
}
}
}
return message;
}
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSockConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/sub");
config.setApplicationDestinationPrefixes("/pub");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOriginPatterns("*");
//.withSockJS();
}
@Bean
public FilterChannelInterceptor filterChannelInterceptor(JwtUtil jwtUtil) {
return new FilterChannelInterceptor(jwtUtil);
}
}
@Component
@RequiredArgsConstructor
public class WebSocketEventListener {
private final RedisTemplate<String, String> redisTemplate;
private final JwtUtil jwtUtil;
@EventListener
public void handleWebSocketConnectListener(SessionConnectEvent event) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
String sessionId = headerAccessor.getSessionId();
String token = headerAccessor.getFirstNativeHeader(JwtUtil.AUTHORIZATION_HEADER);
if (token != null && jwtUtil.validateToken(token)) {
String userEmail = jwtUtil.getUserEmailFromToken(token);
// 세션 ID와 사용자 이메일만 저장
redisTemplate.opsForValue().set("websocket_session:" + sessionId, userEmail);
}
}
@EventListener
public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
String sessionId = event.getSessionId();
redisTemplate.delete("websocket_session:" + sessionId);
}
}
- 계속 수정중이긴하는데, 기본 채팅기능 동작을 확인하고 정리하는 블로그 포스팅
- 처음에는 stompHandler를 사용해서 커넥트를 관리했었는데, 뭐가 문제인지 연결 조차안됨
- 수정의 수정의 수정의.... 무한수정을 거쳐 일단 고정시켜둔 websocket 관련 설정 클래스들
- 레디스에 세션을 이메일로 저장하기 때문에 레디스관련 코드를 추가
- 생각보다 레디스에 저장하는게 많음...
- 세션(+이메일), 특정방에 들어가있는 유저의 이메일, 유저카운트(이건 아직 수정이 필요함), 리프레시토큰, 채팅방목록, 채팅방 채팅메세지 등... 생각보다 여기저기 쓰이고 있어서 이것도 한번쯤 정리가 필요할듯
'기록하기' 카테고리의 다른 글
마이페이지 관련 문제 (1) | 2024.01.02 |
---|---|
샵 관련 문제 (1) | 2024.01.02 |
기술 선택의 이유 정리하기 (1) (0) | 2023.12.18 |
Dependencies [1차 정리] (0) | 2023.12.18 |
AWS EC2 Ubuntu Docker 실행하기 (0) | 2023.12.10 |