1html
本方案基於netty channel的線程安全性與@Sharable中結論,pipeline線程安全前端
增長一個AuthHandler,頂在pipeline最前面安全
鑑權不經過,close channel,經過,remove掉這個鑑權channelhandlersocket
取自jds-im,msgforwarder AuthWsHandleride
------------------------------------------------------------------------------------------------性能
* ctx.pipeline().remove(this);this
1.5url
no remove AuthHandlerspa
channel.attribute.get .net
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