Spring) Websocket Security 문서 정리하기

성승모·2024년 7월 1일
0

https://docs.spring.io/spring-security/reference/6.2/servlet/integrations/websocket.html#websocket-authorization

위 문서를 읽고 웹소켓에 관한 내용을 정리해보려 합니다. (틀린 내용 있을 수 있음!)

버전)
 Spring-freamwork: 6.2.2
 Spring-Security: 6.2.2

웹소켓 인증

  • 웹소켓은 Http와 같은 인증방식을 이용한다.
  • 즉, HttpServleRequest의 Principal은 Websocket에 전달된다.
  • 따라서 Spring Security를 이용하면 자동으로 Principal은 오버라이딩된다.

웹소켓 권한부여

  • 4.0에서 추상클래스를 제공했지만 5.8부턴 API를 제공.
  • @EnableWebSocketSecurity @bean: AuthorizationManager<Message<?>> 을 이용하여 쉽게 이용 가능.
  • endpoint 패턴 특정화 등
@Configuration
@EnableWebSocketSecurity //---(1), (2)
open class WebSocketSecurityConfig {  
    @Bean
    fun messageAuthorizationManager(messages: MessageMatcherDelegatingAuthorizationManager.Builder): AuthorizationManager<Message<*>> {
        messages.simpDestMatchers("/user/**").hasRole("USER") //---(3)
        return messages.build()
    }
}

  ( 1 ): 모든 Inbound Connect 메시지는 유효한 CSRF 토큰을 가져야한다

  ( 2 ): SecurityContextHolder는 모든 inboud 요청에 대해 SimpUser 헤더 속성 안에 사용자들을 채운다

  ( 3 ): /user 로 시작하는 모든 요청은 USER 라는 role이 필요하다.

커스텀 권한요청

@Configuration
open class WebSocketSecurityConfig {
    fun messageAuthorizationManager(messages: MessageMatcherDelegatingAuthorizationManager.Builder): AuthorizationManager<Message<*>> {
        messages
            .nullDestMatcher().authenticated()  //---(1)
            .simpSubscribeDestMatchers("/user/queue/errors").permitAll() //---(2)
            .simpDestMatchers("/app/**").hasRole("USER") //---(3)
            .simpSubscribeDestMatchers("/user/**", "/topic/friends/*").hasRole("USER") //---(4)
            .simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() //---(5)
            .anyMessage().denyAll()  //---(6)

        return messages.build();
    }
}

  ( 1 ): destination이 없는 메시지는 사용자에게 인증을 요청.

  ( 2 ): 모든 사용자들은 /user/queue/erros를 구독할 수 있다.

  ( 3 ): /app 으로 시작하는 Destination을 가진 메시지는 User 권한을 필요로 함.

  ( 4 ): /user 또는 /topic/friends 의 구독은 User 권한을 필요로 함.

  ( 5 ): 모든 Message와 구독은 거부됨.

  ( 6 ): 다른 모든 요청은 거부됨. 모든 처리를 개발자가 놓치지 않기 위해 이를 해놓는 것이 권장됨.

Message 타입에 따른 인증

  • 모든 사용자에게 공지를 보낼 destination인 /topic/system/notifications가 있다. 모든 사용자는 /topic/system/notifications를 !!구독!!해야한다.
  • 하지만 /topic/system/notifications로 메시지를 보내는 것은 방지해야할 것이다. 왜냐면 사용자가 공지를 이용하게 만들지 않기 위해서이다.

Destination에 따른 인증

  • 사용자가 /app/chat으로 메시지를 보낸다.
  • spring에서 메시지를 확인하여 "From" 속성을 통해 유효한지 확인한다.
  • 그 다음에 SimpMessageSendingOperations.convertAndSendToUser를 이용하여 수신자에게 메시지를 보낸다.
  • 그 메시지의 Destination은 /queue/user/messages-<seesion_id>로 바뀔 것이다.
  • 따라서 /queue에 접근은 거부해야 할 것이다.

OutBound 메시지

  • Spring에선 clientInboundChannel 만을 다룬다.
  • 따라서 outbound에 대한 보안은 제공되지 않으며 SUBSCRIBE, DESTINAION에 대한 인증절차로 이를 대체한다.
profile
안녕하세요!

0개의 댓글