auth_duration = Config::get('session')['expire']; //设置成和session相同的过期时间 $this->_redis = Cache::init()->handler(); // redis 句柄 } /** * 登录完成后,调用该方法,在 websocket 服务端注册一个有效token,并产生 token 和 uid 的对应关系记录 * @param $token * @param $adminId * @return void */ public function registerToken($token, $adminId) { // uid 对应的 token列表, 同一个账号,可能存在多个人同时登录的情况,在目前的业务场景下,并未禁止 // 所以要能够实现多个登录终端的对应 $tokenCacheKey = "ayam:push:uid:{$adminId}:token"; $tokenList = $this->_redis->get($tokenCacheKey); $tokenList = json_decode($tokenList, true); empty($tokenList) && $tokenList = array(); $tokenList[$token] = time() + $this->auth_duration; // 限制 token 的个数,超出预设值,剔除最先登录的 if (count($tokenList) > self::TOKEN_LIMIT) { // 限制 TOKEN 数 $tokenList = array_slice($tokenList, -self::TOKEN_LIMIT); } $this->_redis->setex($tokenCacheKey, $this->auth_duration, json_encode($tokenList)); // token 对应的 uid,这样 workerman 那边可以通过 token 查询对应的 uid $cacheKey = "ayam:push:token:{$token}:uid"; $this->_redis->setex($cacheKey, $this->auth_duration, $adminId); } /** * 重置登录token有效 * * @param $token string 查询的token * @param $adminId string 所属用户id * * @return void */ public function resettingToken($token, $adminId) { // uid 对应的 token列表, 同一个账号,可能存在多个人同时登录的情况,在目前的业务场景下,并未禁止 // 所以要能够实现多个登录终端的对应 $tokenCacheKey = "ayam:push:uid:{$adminId}:token"; $cacheKey = "ayam:push:token:{$token}:uid"; if (!$this->_redis->exists($cacheKey)) { $tokenList = $this->_redis->get($tokenCacheKey); $tokenList = json_decode($tokenList, true); empty($tokenList) && $tokenList = array(); $tokenList[$token] = time() + $this->auth_duration; // 限制 token 的个数,超出预设值,剔除最先登录的 if (count($tokenList) > self::TOKEN_LIMIT) { // 限制 TOKEN 数 $tokenList = array_slice($tokenList, -self::TOKEN_LIMIT); } $this->_redis->setex($tokenCacheKey, $this->auth_duration, json_encode($tokenList)); // token 对应的 uid,这样 workerman 那边可以通过 token 查询对应的 uid $this->_redis->setex($cacheKey, $this->auth_duration, $adminId); } } /** * 注销连接 token * @param $token * @param $adminId * @return void */ public function destroyToken($token, $adminId) { $uidCacheKey = "ayam:push:token:{$token}:uid"; $this->_redis->del($uidCacheKey); $tokenCacheKey = "ayam:push:uid:{$adminId}:token"; $tokenList = $this->_redis->get($tokenCacheKey); if (empty($tokenList)) { $tokenList = array(); } else { $tokenList = json_decode($tokenList, true); } if (isset($tokenList[$token])) { // 只清除指定的 token unset($tokenList[$token]); } // 若该uid还存在token,做更新,否则删除key,减少占用 if (count($tokenList) > 0) { $this->_redis->set($tokenCacheKey, json_encode($tokenList)); } else { $this->_redis->del($tokenCacheKey); } } /** * 发送消息给指定的用户 * @param $uid int * @param $data string * @return void */ public function sayToUid($uid, $data) { if (!is_string($data) || empty($data)) { exception('data 参数需为字符串类型'); } empty($uid) && exception('请传入 uid参数'); Gateway::$registerAddress = config('WEBSOCKET_REGISTER_ADDR'); // 数据格式示例:{"error_code":0,"data":{"action":"authSuccess","data":{"code":0,"message":""}}} Gateway::sendToUid($uid, $data); } }