iohao / ioGame

无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你可以很容易的搭建出一个集群无中心节点、集群自动化、分布式的网络服务器;FXGL、Unity、UE、Cocos Creator、Godot、Netty、Protobuf、webSocket、tcp、socket;java Netty 游戏服务器框架;
http://game.iohao.com
GNU Affero General Public License v3.0
834 stars 183 forks source link

WebSocketVerifyHandler使用 #322

Closed molin7596 closed 2 months ago

molin7596 commented 2 months ago
@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest request) {
            // 从 uri 中解析参数
            String uri = request.uri();
            Map<String, String> params = getParams(uri);

            // 开发者可以重写 verify 方法来扩展
            SocketUserSession userSession = userSessions.getUserSession(ctx);
            boolean verify = verify(userSession, params);

            if (verify) {
                //  验证通过后,移除自身;减少消息在 handler 中流动的次数
                ctx.pipeline().remove(this);
            } else {
                // 验证失败,关闭连接或返回错误响应
                FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED);
                ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                return;
            }
        }

        super.channelRead(ctx, msg);
    }

getParams 方法会 将 字符串中的“+” 替换为 “ ”

protected Map<String, String> getParams(String uri) {
        return new QueryStringDecoder(uri)
                .parameters()
                .entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getFirst()));
    }
molin7596 commented 2 months ago

例如 “token = +++abc+abc+abc+++”, 会导致 + 替换为 “ ” ,变成 “token = abc abc abc ”

molin7596 commented 2 months ago
@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest request) {
            // 从 uri 中解析参数
            String uri = request.uri();
            // 解析
            int index = uri.indexOf(prefix);
            String serverToken = uri.substring(index + prefix.length());
            SocketUserSession userSession = userSessions.getUserSession(ctx);
            boolean verify = verifyToken(userSession, serverToken);

            if (!verify) {
                // 验证失败,关闭连接或返回错误响应
                FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED);
                ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                return;
            }
        }
        super.channelRead(ctx, msg);
    }

重写之后一直设置 userId 失败 boolean success = UserIdSettingKit.settingUserId(flowContext, userId ); // 这个 settingUserIdMessageResponse.isSuccess() is false

if (Objects.isNull(settingUserIdMessageResponse) || !settingUserIdMessageResponse.isSuccess()) {
    return false;
}
iohao commented 2 months ago

例如 “token = +++abc+abc+abc+++”, 会导致 + 替换为 “ ” ,变成 “token = abc abc abc ”

QueryStringDecoder 不支持这种特殊字符串。有特殊内容的,可重写 getParams 方法

https://github.com/iohao/ioGame/blob/2e0ed24155f41adb5a96815427b198137a4cfa90/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/ws/WebSocketVerifyHandler.java#L92-L98

getParams 方法返回的 map 会传到 verify 方法中。

https://github.com/iohao/ioGame/blob/2e0ed24155f41adb5a96815427b198137a4cfa90/external/external-netty/src/main/java/com/iohao/game/external/core/netty/handler/ws/WebSocketVerifyHandler.java#L74-L90

相关文档 - ws token 鉴权、校验 (yuque.com)

molin7596 commented 2 months ago

好的 谢谢 ,没看清楚 以为 getParams 是private ,发现是 protected