【分布式WebSocket - 5】SprintBoot集成STOMP协议,session权限管理

本文介绍了如何在SpringBoot中使用WebSocket和STOMP协议时,通过配置拦截器实现用户连接与订阅权限的管理,包括客户端认证授权、Token验证以及消息发送的权限控制。详细步骤包括配置WebSocketMessageBroker、自定义ChannelInterceptor和H5客户端的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


        SpringBoot在集成STOMP协议时,有些时候需要控制session的连接权限、订阅权限等。例如禁止某些用户连接,控制用户只能订阅自己的主题等。而且在这种场景权限的控制比较简单,一般情况下,可以使用拦截器,进行权限管理。

架构图

image-20210615142353037

  1. 客户端去业务系统进行认证授权,将授权信息存放redis。并且返回客户端token。
  2. 客户端收到token,携带token连接推送服务器。推送服务器判断token,有效则认证通过。

每个业务服务器的代码都基本一致,就不做展示,直接示例下第二步的代码。

服务端代码

配置拦截器

WebSocketConfig

package com.test.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.WebSocketMessageBrokerStats;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
{
   // 启用一个简单的基于内存的消息代理
   @Override
   public void configureMessageBroker(MessageBrokerRegistry config) {
      //通过/topic 开头的主题可以进行订阅
      config.enableSimpleBroker("/topic");
      //send命令时需要带上/app前缀
      config.setApplicationDestinationPrefixes("/app");
   }
   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {
      //连接前缀
      registry.addEndpoint("/gs-guide-websocket")
            .setAllowedOrigins("*")  // 跨域处理
            .withSockJS();  //支持socketJs
   }
   @Override
   public void configureClientInboundChannel(ChannelRegistration registration) {
      //设置拦截器,这儿是个数组, 可添加多个
      registration.interceptors(new MyChannelInterceptor());
   }
}

MyChannelInterceptor类,示例中暂时写了连接事件和订阅事件,可在这两个事件中自行处理对应的逻辑,权限验证等等。

@Slf4j
public class MyChannelInterceptor implements ChannelInterceptor
{
   @Override
   public Message<?> preSend(Message<?> message, MessageChannel channel) {
      StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
      StompCommand command = accessor.getCommand ();
      if(command == StompCommand.CONNECT){
         String userId = accessor.getFirstNativeHeader ("userId");
//       String token = accessor.getFirstNativeHeader ("token");
         log.info ("-------有用户连接-------");
         //todo 连接时可以做权限验证

      }else if (command == StompCommand.SUBSCRIBE){
         log.info ("-------有用户订阅{}-------",accessor.getDestination ());
      }

      return message;
   }
}

StompCommand是一个枚举类,里面有STOMP的连接事件,有连接事件、订阅事件、取消订阅、发送事件等等。

public enum StompCommand {

   // client
   STOMP(SimpMessageType.CONNECT),
   CONNECT(SimpMessageType.CONNECT),
   DISCONNECT(SimpMessageType.DISCONNECT),
   SUBSCRIBE(SimpMessageType.SUBSCRIBE, true, true, false),
   UNSUBSCRIBE(SimpMessageType.UNSUBSCRIBE, false, true, false),
   SEND(SimpMessageType.MESSAGE, true, false, true),
   ACK(SimpMessageType.OTHER),
   NACK(SimpMessageType.OTHER),
   BEGIN(SimpMessageType.OTHER),
   COMMIT(SimpMessageType.OTHER),
   ABORT(SimpMessageType.OTHER),

   // server
   CONNECTED(SimpMessageType.OTHER),
   RECEIPT(SimpMessageType.OTHER),
   MESSAGE(SimpMessageType.MESSAGE, true, true, true),
   ERROR(SimpMessageType.OTHER, false, false, true);
   }

这些事件说明也很容易理解,是一些STOMP协议的基本事件

H5代码

        一般情况下,在进行webSocket连接时,都已经获取到了用户信息,即使没有用户信息,在当前的js页面也会有一个唯一的客户端Id。在连接的时候将客户端的信息添加到请求头。示例代码中,提交了userId,实际情况可自行修改。

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    var userId = 1;
    stompClient.connect({'userId':userId}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
       stompClient.subscribe('/topic/user'+userId, function (greeting) {
              showGreeting(JSON.parse(greeting.body).content);
       },{'userId':userId});
    });
}

STOMP.js说明文档

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叁滴水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值