본문 바로가기
Spring

웹소켓 연결 장애

by 위시우 2024. 4. 11.
  1. 웹소켓 연결

Authorization header 를 추가하여 웹소켓 초기 연결에 성공

const socket = new SockJS(`http://localhost:8080/ws\`, {
headers: {
Authorization: `Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJya2R0amR3bC01QGhhbm1haWwubmV0IiwiYXV0aCI6IlVTRVIiLCJleHAiOjE3MTU5MjU2NTQsImlhdCI6MTcxMjMyNTY1NH0.YL6N05jfWxrIfV07ko4qc6WtiCtTEC6PhNiL0gqRNz0`, // TODO : 헤더에 토큰 넣어야함
},
})

 

  • 웹소켓 연결 CONNECT 시에만 Authorization header 를 추출 후
    SecurityContextHolder.getContext().setAuthentication(authentication); 에 authentication 을 추가하도록 하였음
  • 기대 효과 :connection 을 맺은 후에는 SecurityContextHolder에 등록된 authentication 으로 User 정보를 가져오는 것
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
// 연결 요청시 JWT 검증
if (StompCommand.CONNECT.equals(accessor.getCommand()) || StompCommand.SEND.equals(accessor.getCommand())) {
log.info(String.valueOf(accessor.getCommand()));
// Authorization 헤더 추출
List authorization = accessor.getNativeHeader("Authorization");
if (authorization != null && !authorization.isEmpty()) {
String jwt = authorization.get(0).substring(7);
try {
// JWT 토큰 검증
Claims decodedJWT = jwtUtil.getUserInfoFromToken(jwt);
String email = decodedJWT.getSubject();
// 사용자 정보 조회
Member member = memberRepository.findByEmail(email).orElseThrow(() ->
new CustomException(ErrorCode.NOT_EXIST_USER)
);
                // 사용자 인증 정보 설정  
                UserDetailsImpl userDetails = new UserDetailsImpl(member);  
                UsernamePasswordAuthenticationToken authentication =  
                        new UsernamePasswordAuthenticationToken(  
                                userDetails, null, userDetails.getAuthorities());  
                SecurityContextHolder.getContext().setAuthentication(authentication);  
            } catch (RuntimeException e) {  
                log.error("JWT Verification Failed: " + e.getMessage());  
                return null;  
            } catch (Exception e) {  
                log.error("An unexpected error occurred: " + e.getMessage());  
                return null;  
            }  
        } else {  
            // 클라이언트 측 타임아웃 처리  
            log.error("Authorization header is not found");  
            return null;  
        }  
    }  
    return message;  
}  

 

하지만
userDetails 의 payload value 가 empty 라서 발생한 문제

Unhandled exception from message handler method

org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException: Could not resolve method parameter at index 1 in public void cohttp://m.sparta.moit.domain.chat.controller.ChatController.sendChat(java.lang.Long,com.sparta.moit.global.security.UserDetailsImpl,com.sparta.moit.domain.chat.dto.SendChatRequestDto): 1 error(s): [Error in object 'userDetails': codes []; arguments []; default message [Payload value must not be empty]]
at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:128) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:118) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:147) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:115) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:567) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:528) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:93) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:522) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:457) ~[spring-messaging-6.1.5.jar:6.1.5]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:152) ~[spring-messaging-6.1.5.jar:6.1.5]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]

```

댓글