Workerman的Event使用JWT身份认证导致的用户信息共享

以下是 WS 连接后进行 JWT 认证和 Client 绑定的代码

public static function onWebSocketConnect($client_id, $data)
    {
//        \Log::notice('WK:' . json_encode($data));
        $data_get = $data['get'];
        $res = [
            'type' => 'connection',
            'status' => 'error'
        ];
        // 判断token
        if (!isset($data_get['token'])) {
            $res['msg'] = 'Token不存在';
            Gateway::sendToClient($client_id, json_encode($res, JSON_UNESCAPED_UNICODE));
            Gateway::closeClient($client_id);
        } else {
            // 判断格式是否正确
            if (count(explode('.', $data_get['token'])) !== 3) {
                $res['msg'] = 'Token格式错误';
                Gateway::sendToClient($client_id, json_encode($res, JSON_UNESCAPED_UNICODE));
                Gateway::closeClient($client_id);
            } else {
                // 获取登陆的用户
                $user = null;
                $user = auth('api')->setToken($data_get['token'])->user();
                if (!$user) {
                    $res['msg'] = 'Token格式错误';
                    Gateway::sendToClient($client_id, json_encode($res, JSON_UNESCAPED_UNICODE));
                    Gateway::closeClient($client_id);
                } else {
                    $res['status'] = 'success';
                    $res['msg'] = $user->toArray();
                    Gateway::sendToClient($client_id, json_encode($res, JSON_UNESCAPED_UNICODE));
                    Gateway::bindUid($client_id, $user->id);
                }
            }
        }
    }

出现的问题是,当用户 1 访问后,用户 2345… 获取到的用户信息全都是用户 1 的信息,所有的 ClientId 也都被绑定到了用户 1 的上边。也就是最核心的这一句
$user = auth('api')->setToken($data_get['token'])->user();
这要第一次 setToken 后无论后边 Token 的值如何改变 $user 都是第一个用户,求解!

附言 1  ·  4年前

解决方案,不生成对象,只使用 JWT 解析用户 ID。

$user_id = JWTAuth::setToken($data_get['token'])->getPayload()->get('sub');
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

猜测问题应该是出在 auth ('api')->setToken () 这一步,常驻进程内存不会释放,在 setToken 方法中是否存在策略如果没有 token 则设置,如果已有则不更新,那么这就会出现你的问题,因为用户 id 已经存在(来自第一次设置的 token)所以将不会更新了,导致后面所有的用户使用的都是使用同一个用户 ID。

而出现这个问题最主要的原因是 Laravel 在常驻进程中没有重新初始化,这意味着在这个进程中 Laravel 已存在的数据将会共享,这样一来在很多场景下会有意想不到的额外问题。

4年前 评论
MyPuppet (楼主) 4年前
yzbfeng 2年前
yzbfeng 2年前
Anoxia (作者) 2年前
讨论数量: 14

我也正在纠结这个。

4年前 评论
MyPuppet (楼主) 4年前

看看 auth ('api')->setToken ()->user () 方法实现的代码。不行你可以自己实现一个 jwt 类

4年前 评论
MyPuppet (楼主) 4年前
pan_zoe 4年前
MyPuppet (楼主) 4年前
pan_zoe 4年前

猜测问题应该是出在 auth ('api')->setToken () 这一步,常驻进程内存不会释放,在 setToken 方法中是否存在策略如果没有 token 则设置,如果已有则不更新,那么这就会出现你的问题,因为用户 id 已经存在(来自第一次设置的 token)所以将不会更新了,导致后面所有的用户使用的都是使用同一个用户 ID。

而出现这个问题最主要的原因是 Laravel 在常驻进程中没有重新初始化,这意味着在这个进程中 Laravel 已存在的数据将会共享,这样一来在很多场景下会有意想不到的额外问题。

4年前 评论
MyPuppet (楼主) 4年前
yzbfeng 2年前
yzbfeng 2年前
Anoxia (作者) 2年前

之前一个项目用的 passport 没找到可以直接解析 校验 token 的办法,只能直接转发请求到当前项目的某个接口。。。

3年前 评论