• netty+websocket模式下token身份验证遇到的问题


    转https://blog.csdn.net/alwaysRise/article/details/121002198

    netty+websocket下pipeline中handler无法传递的问题
    在ChannelPipeline中责任链的传递

    点击查看代码
    ChannelPipeline pipeline = socketChannel.pipeline();
    
    //websocket协议本身是基于http协议的,所以这边也要使用http解编码器
    pipeline.addLast(new HttpServerCodec());
    //以块的方式来写的处理器
    pipeline.addLast(new ChunkedWriteHandler());
    //netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
    pipeline.addLast(new HttpObjectAggregator(8192));
    
    //        pipeline.addLast(new ReadTimeoutHandler(60));
    
    pipeline.addLast(httpRequestHandler);
    //ws://server:port/context_path
    //ws://localhost:9999/ws
    //参数指的是contex_path
    pipeline.addLast(new WebSocketServerProtocolHandler("/xdong",true));
    
    //websocket定义了传递数据的6中frame类型
    pipeline.addLast(xdongTextWebSocketFrameHandler);
    

    在责任链中有两个我自定义的handler,分别是httpRequestHandler和xdongTextWebSocketFrameHandler,这两个handler的作用分别是处理http请求下的token身份验证和完成握手升级以及处理握手完成之后接收ws客户端传入的消息。

    但是在我的代码过程中发生了问题,客户端能成功和服务器建立通道,但是却无法完成后续的消息传输,网上在线的ws测试客户端和我的服务端建立连接的时候也提示未收到服务端的握手包。

    经过大佬的排查发现我在我的handler中并没有通过fire时间将消息给责任链中的下一个handler处理,实际上我虽然建立了通道但是却没有完成握手,更无法处理消息。

    其中三个重要的handler在责任链中的顺序是这样的:

    点击查看代码
    pipeline.addLast(httpRequestHandler);
    //ws://server:port/context_path
    //ws://localhost:9999/ws
    //参数指的是contex_path
    pipeline.addLast(new WebSocketServerProtocolHandler("/xdong",true));
    
    //websocket定义了传递数据的6中frame类型
    pipeline.addLast(xdongTextWebSocketFrameHandler);
    

    httpRequestHandler这个handler放第一个的原因是第一次握手的时候,请求实际上还是个http请求, 我可以拿到url中的token完成身份验证的工作。但是完成了之后还需要调用下一个handler完成http到ws协议的升级。

    WebSocketServerProtocolHandler这个handler是io.netty包中自带的handler用来完成http协议到websocket协议的升级, 并且明确提到消息处理的handler必须在该handler之后。
    image
    xdongTextWebSocketFrameHandler是一个消息处理的handler,在成功建立ws连接后用来接收客户端传输的消息。

    在pipeLine中的加入顺序都是addLast, 所以都是有顺序的。在channelRead0方法中处理完当前的逻辑之后需要通过fire事件触发下一个InboundHandler。方法就是ctx.fireChannelRead(((FullHttpRequest) msg).retain())
    @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof FullHttpRequest) { handleHttpRequest(ctx, (FullHttpRequest) msg); ctx.fireChannelRead(((FullHttpRequest) msg).retain()); } else if (msg instanceof WebSocketFrame) { ctx.fireChannelRead(((WebSocketFrame) msg).retain()); } }

  • 相关阅读:
    s2sh的MVC执行流程和执行原理
    码支付-个人支付接口-个人收款
    notepad++ FTP同步插件【FanFtpTools】2.0
    自己做的notepad++ FTP同步插件【FanFtpTools】
    thinkphp高并发抢购代码测试-解决高并发下的超卖问题!
    thinkphp5.0 与thinkphp5.1 db()函数的区别
    thinkphp5.1 长连接-单例模式测试之二
    thinkphp5.1长连接-单例模式测试!
    php 全文搜索引擎-讯搜使用
    在线WEB开发编辑器,edt.df5d.com
  • 原文地址:https://www.cnblogs.com/sheseido/p/15580024.html
Copyright © 2020-2023  润新知