使用WebSocket如何解析请求token进行用户校验

一、定义websocket请求拦截器( 主要是这一步 )

@Component
@Slf4j
public class BootWebSocketInterceptor extends HttpSessionHandshakeInterceptor {

    
    private static String socketUrl = "/ws";
    private static String tokenHeader = "socketToken";

    //集成 HttpSessionHandshakeInterceptor ,重写它的握手前和握手后两个方法
    //握手前
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
        //获取请求路径,这个请求路径我们可以自己定义吗(即,请求哪个路径表示要进行websocket请求连接)
        String contextPath = servletRequest.getRequestURI(); 

        //判断这个请求路径是不是我们定义的建立websocket请求的路径
        if (Objects.equals(contextPath, socketUrl)) {
            //相等,表示这个请求是需要建立websocket连接的
            String token = servletRequest.getParameter(tokenHeader);//获取请求token
            //进行token相关的校验
            //token是否为空
            if (StrUtil.isBlank(token)) {
                return false; //返回false,表示握手不成功
            }
            // 验证令牌有效性
            boolean tokenExpired = *****;//自己项目的校验方法
            if (tokenExpired) {
                return false;
            }
            //有需要的业务可以在这里加

            Integer uid = *****;//调用自己业务的解析token的方法拿到用户id
            log.info("握手成功:" + uid);
            //将参数放到attributes,供后面使用
            attributes.put(SocketConstants.USER_ID, uid);
            return super.beforeHandshake(request, response, wsHandler, attributes);
        }
        return false;
    }

    // 握手后
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                               WebSocketHandler wsHandler, Exception ex) {
        super.afterHandshake(request, response, wsHandler, ex);
    }

二、定义websocket处理器

/**
 * 聊天消息的 socket 处理
 */
@Slf4j
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    //定理一个map来缓存websocket的Session
    private static final ConcurrentHashMap<Integer, List<WebSocketSession>> POOL_SESSION = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        //获取第一步中解析的uid
        Object uid = session.getAttributes().get(SocketConstants.USER_ID);
        if (uid != null && lId != null) {
            Integer liveId = Integer.valueOf((String) lId);
            log.info("连接成功:" + uid + ",当前总用户数:" + POOL_SESSION.size());
            //这里写建立成功之后需要的业务
        }
    }

    /**
     * 接收消息事件
     */
    @SneakyThrows
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        // 获得客户端传来的消息
        String payload = message.getPayload();
        log.info("server 接收到客户端消息 {}", payload);
        session.sendMessage(new TextMessage("ok"));
    }

    /**
     * socket 断开连接时
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        //断开连接的业务代码
    }

    
    public PushResultVo sendMsg(Integer uid, Dict transmission) {
        //定义发送消息的方法
        //提供相关参数,找到需要接收信息的WebSocketSession
        session.sendMessage(new TextMessage(JSONUtil.toJsonStr(transmission)));//发送消息
      
    }

  

}

三、定位websocket配置类

@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {

    private final ChatWebSocketHandler chatWebSocketHandler;

    private final BootWebSocketInterceptor bootWebSocketInterceptor;


    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }


    //注册请求拦截器、处理器
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry
                .addHandler(chatWebSocketHandler, "/ws") //对这个路径(即我们定义的websocket的请求路径)进行拦截处理
                .addInterceptors(bootWebSocketInterceptor)
                .setAllowedOrigins("*");
    }

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值