@Component
public class SimpleWebSocketHandler extends TextWebSocketHandler {
}
-클라이언트 A,B, C 가 각각connect 요청을 하면 서버의 websocket handler가 서버의 메모리에 클라이언트의 정보를 각각 저장
주의: http 프로토콜이 아니기 때문에 헤더에 토큰을 넣어서 보낼 수도 없고 ws에 토큰을 넣어 보낸다고 하더라도 authentication을 수행 할 수 없다. 따라서 filter에서 제외처리해야한다.
그러면 서버에서 사용자 인증을 어떻게 할까?
package com.example.chatserver.chat.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
//connect로 요청이 들어 올때 처리할 핸들러
@Component
@Slf4j
public class SimpleWebSocketHandler extends TextWebSocketHandler {
//여러 사용자가 한꺼번에 올수 있으니
private final Set<WebSocketSession> sessions = ConcurrentHashMap.newKeySet();
public SimpleWebSocketHandler() {
super();
}
/**
* 연결 되면 set에 사용자의 정보를 등록
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//세션에는 사용자의 ip, MAC 과 같은 정보가 들어있음
//세션을 서버에 저장해둠
sessions.add(session);
log.info("Connect: {}", session.getId());
}
/**
* 사용자의 메세지를 전송하는 메소드
* @param session
* @param message
* @throws Exception
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//payload: 사용자의 메세지가 담겨 있음
String payload = message.getPayload();
log.info("received message : {}", payload);
//반복문 돌며 전송
for(WebSocketSession s : sessions){
if(s.isOpen()){
s.sendMessage(new TextMessage(payload));
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessions.remove(session);
log.info("disconnected!!");
}
/**
* 연결이 끊기면 세션을 날려줌
* @return
*/
@Override
public boolean supportsPartialMessages() {
return super.supportsPartialMessages();
}
}
@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
private final SimpleWebSocketHandler simpleWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// "/connect url로 연결 요청이 들어오면 , 핸들러 클래스가 처리"
registry.addHandler(simpleWebSocketHandler, "/connect")
//securityConfig에서의 cors예외는 http예외임
//따라서 websocket 프로토콜에 대한 요청에 대해서는 별도의 cors 설정이 필요
.setAllowedOrigins("http://localhost:3000");
}
}
@EnableWebSocket
과 WebSocketConfigurer
구현으로 웹소켓 엔드포인트 등록TextWebSocketHandler
를 상속받아 메시지 처리setAllowedOrigins("http://localhost:3000")
WebSocketHandlerDecorator
로 인증 로직 감쌈