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

posted on 2018-09-17 18:11  silyvin  阅读(6626)  评论(0编辑  收藏  举报