zoukankan      html  css  js  c++  java
  • netty tcp(WebSocket)鉴权2个方案

    1

    本方案基于netty channel的线程安全性与@Sharable中结论,pipeline线程安全

    增加一个AuthHandler,顶在pipeline最前面

    鉴权不通过,close channel,通过,remove掉这个鉴权channelhandler

     取自jds-im,msgforwarder AuthWsHandler

    ------------------------------------------------------------------------------------------------

     * ctx.pipeline().remove(this);

    1.5

    no remove AuthHandler

        channel.attribute.get    

        null - 是否鉴权请求

          否 close

          是 鉴权

        not null 直接放行ctx.fireChannelRead

    2

    connect时鉴权,将信息放在ws url中

    前端:ws = new WebSocket(WS_URL + ";" + getCookie('token'));

    服务端在握手前:

    public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    
        private static final Logger logger = LoggerFactory.getLogger(HttpRequestHandler.class);
    
        public static AttributeKey<String> TOKEN = AttributeKey.valueOf("token");
        public static AttributeKey<String> USERNAME = AttributeKey.valueOf("userName");
    
        @Override
        public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
            String url = request.getUri();
    
            if(-1 != url.indexOf("/ws")) {
    
                String temp [] = url.split(";");
                if(temp.length >= 2) {
                    String token = URLDecoder.decode(temp[1], "UTF-8");
                    ctx.channel().attr(TOKEN).set(token);
                }
                request.setUri("/ws");
                // 传递到下一个handler:升级握手
                ctx.fireChannelRead(request.retain());
            } else {
                logger.error("not socket");
                ctx.close();
            }
        }
    

      

    握手后:

        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
            if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
    
                // 移除性能更加
                ctx.pipeline().remove(HttpRequestHandler.class);
    
                boolean hasAuth = false;
                String userName = null;
                String token = ctx.channel().attr(HttpRequestHandler.TOKEN).get();
                if(token == null || "".equals(token)) {
                    logger.warn("no token");
                } else {
                    userName = GlobalContext.channelUser.get(token);
                    if(userName != null && !"".equals(userName)) {
                        ctx.channel().attr(HttpRequestHandler.USERNAME).set(userName);
                        hasAuth = true;
                    } else {
                        logger.warn("no user");
                    }
                }
                if(hasAuth) {
                    String up = userName + "[connected]";
                    logger.info(up);
                    //    for(int i=0; i<100; ++i)
                    ctx.writeAndFlush(up);
                    group.add(ctx.channel());
                } else {
                    String noToken = "[您的token非法,请重新登录]";
                    logger.warn(noToken);
                    ctx.writeAndFlush(noToken).addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture channelFuture) throws Exception {
                            channelFuture.channel().close();
                        }
                    });
                }
    

      

    实践具体位置参见:https://www.cnblogs.com/silyvin/articles/9590595.html

  • 相关阅读:
    python day01
    Mac上安装pexpect
    raid
    SSL证书制作
    linux grep命令详解
    第一轮迭代小组成员分数分配
    M1事后分析报告(Postmortem Report)
    软件发布说明
    测试报告
    week 9 scenario testing
  • 原文地址:https://www.cnblogs.com/silyvin/p/9663641.html
Copyright © 2011-2022 走看看