1. WebSocket 인증 및 Spring Security와 충돌 문제
1)개요
WebSocket 연결 시 Authorization 헤더에 Access Token이 포함되지 않아 Spring Security의 인증이 실패하여 연결이 차단 됨
(인증된 사용자만 접근할 수 있도록 하기 위해 단순 로그인 후 토큰 값을 하드코딩하여 WebSocket 연결을 테스트 하는 과정에서 문제 발생)
알고보니 Access Token이 쿠키에 저장되고 있어서 인증이 되지 않았고, 이를 해결하기 위해 WebSocket 연결 시 Headers의 Cookie 값에 자동으로 쿠키에 저장된 토큰 값을 불러오는 방식으로 로직을 변경해봤지만 인증이 여전히 되지 않았음
2)문제상황
- Access Token의 쿠키 기반 저장
- Spring Security 구현하는 과정에서 보안을 위해 Access Token 값을 Cookie에 저장하였는데, WebSocket 요청은 기본적으로 Authorization 헤더를 사용하여 토큰을 전달하는 방식이므로, header에 토큰 값이 들어가지 않아 인증이 되지 않았음
- CSRF 정책 문제(비활성화와 헤더 누락)
- Access Token을 Cookie에 저장하고, WebSocket 요청을 허용하기 위해 CSRF 보호를 비활성화하였다. 하지만 WebSocket 요청 시 Authorization 헤더에 토큰이 포함되지 않았기 때문에 인증이 이루어지지 않았고, CSRF 보호가 비활성화된 상태에서도 요청이 차단되었습니다.
- =CSRF 보호의 문제가 아닌 WebSocket의 인증 방식(Authorization헤더에 AccessToken이 있어야함)과 Authorization 헤더누락(Access Token은 Cookie에 저장되있음)의 충돌의 문제
3)해결
Access Token을 쿠키에 저장하지 않고, Response Body로 반환하도록 수정 후 클라이언트 측에서 WebSocket 연결 요청을 보낼 때 Authorization 헤더에 Access Token을 포함시켜 토큰 전달함. → 인증 됨
4)결론
수정 후 WebSocket 인증이 성공적으로 이루어졌고, 연결 및 메시지 송수신이 정상적으로 동작하는 것을 확인
2. CORS 정책으로 인한 WebSocket 연결 불가
1) 개요
실시간 채팅을 구현하는 과정에서 WebSocket이 CORS 정책에 의해 차단되는 문제 발생
WebSocket 요청이 특정 도메인에서 허용되지 않아 프론트엔드에서 백엔드 서버로의 연결이 불가능한 상황
2) 문제 상황
클라이언트에서 WebSocket 연결을 시도했지만, CORS 정책 위반 오류가 발생해 브라우저의 보안 정책에 따라 WebSocket 연결이 제한되었고, 백엔드에서 CORS 설정이 올바르게 적용되지 않은게 원인
403 Forbidden 에러와 함께 WebSocket handshake가 실패하여 연결이 이루어지지 않음
3) 해결
Spring Security에서 CORS 설정 추가
CORS 정책을 해결하기 위해 SecurityConfig에서 허용 설정을 추가, Spring Security에서는 CorsConfigurationSource를 설정하여 특정 도메인에서의 WebSocket 연결을 허용할 수 있다.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.httpBasic(AbstractHttpConfigurer::disable)
.cors(cors -> cors.configure(httpSecurity))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
.requestMatchers("/map", "location", EndpointConstants.AUTH_SIGNUP, EndpointConstants.AUTH_LOGIN).permitAll()
.requestMatchers("/api/location/**").authenticated()
.requestMatchers("/api/admins/**").hasRole("ADMIN")
.requestMatchers("/ws-chat/**").permitAll()
.requestMatchers("/test").permitAll()
.anyRequest().authenticated()
)
4) 결론
- Spring SecurityConfig에서 CORS 설정을 추가하여 WebSocket 연결이 정상적으로 이루어짐을 확인
- WebSocket 요청이 특정 도메인에서 허용되었으며, 추가적인 CORS 문제 없이 데이터 송수신이 가능
3. WebSocket Security 적용 중 인증 문제 발생
1) 개요
실시간 채팅 기능을 구현하면서 WebSocket 연결 시 JWT 인증을 추가하려고 Spring Security를 활용하려고 했지만, WebSocket은 HTTP 요청과 다르게 한 번 연결되면 지속 유지되는 특성이 있어, 기존의 HTTP 기반 인증 방식과 충돌 발생
WebSocket 보안을 강화하기 위해 Spring Security의 WebSocket 보안 설정(@EnableWebSocketSecurity)을 적용
하지만, 이 어노테이션을 사용하면 CSRF 토큰이 정상적으로 인코딩/디코딩되지 않는 문제가 발생했고, 결과적으로 WebSocket 연결이 실패하는 상황이 발생
2) 문제 상황
- @EnableWebSocketSecurity 적용 시 CSRF 토큰 처리 문제 발생
- 기본적으로 Spring Security는 CSRF 보호를 활성화하며, WebSocket 보안 설정도 이를 따르고 있음
- 하지만, @EnableWebSocketSecurity를 사용하면 CSRF 토큰이 정상적으로 인코딩/디코딩되지 않는 문제가 발생하여 CSRF 토큰이 올바르게 전달되지 않아 인증이 실패했고, WebSocket 연결이 차단됨
- WebSocket 연결이 정상적으로 이루어지지 않음
- 기존 Spring Security 설정에서는 Authorization 헤더를 통해 JWT 인증을 수행하도록 구성하지만 WebSocket 연결 과정에서는 Authorization 헤더가 기본적으로 포함되지 않아 인증 실패
- WebSocket 보안 설정이 제대로 적용되지 않음
- @EnableWebSocketSecurity는 Spring Security의 WebSocket 보안 기능을 활성화하는 어노테이션이지만, 아직 완전히 지원되지 않는 기술이라 일부 기능이 정상적으로 동작하지 않음
- WebSocket의 메시지 송수신 과정에서 추가적인 보안 검증이 필요했지만, 이 과정에서 Spring Security 설정이 제대로 반영되지 않음
3) 해결
- @EnableWebSocketSecurity 설정 제거
- Spring Security의 WebSocket 보안 기능이 아직 완벽하게 지원되지 않으므로 해당 설정을 제거하고 대신, WebSocket 보안을 StompHandler에서 직접 구현하는 방향으로 변경
- StompHandler에서 메시지 송수신 시 JWT 인증 검증 추가
- WebSocket은 한 번 연결되면 지속적으로 사용되므로, 메시지를 송수신할 때마다 인증을 수행하도록 변경
- StompHandler에서 Authorization 헤더를 읽어 JWT 토큰을 검증하는 방식으로 인증 로직을 직접 구현
4) 결론
- @EnableWebSocketSecurity는 아직 미완성된 기능이라 CSRF 토큰 처리 문제와 인증 문제 유발
- WebSocket 요청에서는 CSRF 보호가 불필요하므로, 이를 비활성화하여 문제를 해결
- 결과적으로 WebSocket 보안을 Spring Security 설정에 의존하지 않고, StompHandler에서 직접 인증을 처리하는 방식으로 변경
- WebSocket과 HTTP 요청은 인증 방식이 다르므로, 이를 구분하여 적적한 방식으로 보안을 적용해야 한다는 점을 배움
'TIL(Today I Learned) > 트러블슈팅' 카테고리의 다른 글
[트러블 슈팅 / ~ 최종발표] 최종 프로젝트 : 9kcal. 오늘 뭐 먹지? (0) | 2025.04.19 |
---|---|
[트러블 슈팅] Trello(칸반보드) 프로젝트 (0) | 2025.02.21 |
[트러블 슈팅] JPA 심화 개인과제 (1) | 2024.12.19 |
[트러블 슈팅] 아웃소싱 프로젝트 (2) | 2024.12.07 |
[트러블 슈팅] Spring 심화 개인과제 (1) | 2024.11.29 |