Netty websocket服务在url上携带参数

内容纲要

需求

  • 在连接websocket时,对连接进行权限校验的方式一般为将身份信息放在url上或者连接上websocket后立马发送校验信息
    1. 放在url上的方式在连接的第一时刻就可以对该连接进行身份校验,可以避免连接浪费和编码复杂度,Tomcat-websocket对该方式有良好的支持,但是Netty在并没有对该方式进行支持,需要自己编码实现
    2. 连接后第一时间发送身份信息,该方式可以做到身份校验,但是链接之后需要定时检查用户是否授权,未授权则关闭通道,在此期间则会占用一个链接通道,降低服务器的连接数量

Netty中不支持的原因

  • Netty实现WebSocket只需要在pipeline中添加一个WebSocketServerPortocolHandler就可以实现ws接口的暴露,因为安全问题,ws并不推荐通过queryString携带信息,所以Netty中WebSocketServerPortocolHandler模式的构造器要求连接建立是传入的URL与程序指定的路径完全匹配,所以该类中的checkStartsWith(校验url中前缀与指定的url相同即可)默认为false

Netty中pipeline的运行顺序

  • 在Netty中,pipeline运行顺序为 header->入站处理器->tail->出站处理器->header

解决方案

  • 我们可以在添加WebSocketServerPortocolHandler之前添加我们的InboundHandler并重写channelRead方法,并判断msg是否为FullHttpRequest(代表一个新的连接接入),获取到路由信息后,再将请求重定向回WebSocketServerPortocolHandler制定的路径即可
  • 演示url: ws://local:port/path/{token} {token}为携带的路径参数
    # 拦截器重新方法
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //用户信息校验
        if (msg instanceof FullHttpRequest) {
            FullHttpRequest request = (FullHttpRequest) msg;
            String uri = request.uri();
            String token = uri.split("/")[2];
            System.out.println(token);
            #重定向到/path
            request.setUri("/path");
            super.channelRead(ctx, request);
        } else {
            super.channelRead(ctx, msg);
        }
    }

    InboundHandler一定要在添加WebSocketServerPortocolHandler之前添加到pipeline中

THE END
分享
二维码
< <上一篇
下一篇>>