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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM