_device = Yii::$app->request->getDevice(); $this->_deviceInfo = Yii::$app->request->getDeviceInfo(); } /** * 首次以用户名和密码的方式登录 * @param IdentityInterface $identity * @return bool * @throws HttpException */ public function loginWithUAndP(IdentityInterface $identity){ if ($this->beforeLogin($identity, false, 0)) { $id = $identity->getId(); $ip = Yii::$app->getRequest()->getUserIP(); $this->_userId = $identity['ID']; $this->_apiIdentity = $identity; $this->_userInfo = [ 'id' => $identity['ID'], 'adminName' => $identity['ADMIN_NAME'], 'roleId' => $identity['ROLE_ID'], 'accessTokenUpdatedAt' => Date::nowTime(), 'ip' => $ip, ]; Admin::updateAll(['LAST_LOGIN_IP' => $ip, 'LAST_LOGIN_AT' => Date::nowTime()], 'ID=:ID', [':ID'=>$identity['ID']]); $userToken = AdminToken::findOne(['ADMIN_ID' => $identity['ID']]); if(!$userToken){ $userToken = new AdminToken(); $userToken->ADMIN_ID = $identity['ID']; $userToken->CREATED_AT = Date::nowTime(); $userToken->save(); } $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'access'); $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'refresh'); $this->afterLogin($identity, false, 0); } return !$this->getIsGuest(); } public function afterLogin($identity, $cookieBased, $duration) { parent::afterLogin($identity, $cookieBased, $duration); // 记录管理员登录日志 // Log::adminLogin(); } /** * 已AccessToken方式登录(即平时直接访问) * @param string $token * @param null $type * @return null|IdentityInterface */ public function loginByAccessToken($token, $type = null) { /* @var $class IdentityInterface */ $class = $this->identityClass; $userId = $this->_userId = $class::findIdentityByAccessToken($token, $type); if($userId){ $this->_userInfo = [ 'id' => $userId, 'adminName' => Yii::$app->tokenRedis->hget($token, 'ADMIN_NAME'), 'roleId' => Yii::$app->tokenRedis->hget($token, 'ROLE_ID'), 'accessTokenUpdatedAt' => Yii::$app->tokenRedis->hget($token, 'TOKEN_UPDATED_AT'), 'ip' => Yii::$app->getRequest()->getUserIP(), ]; return $userId; } else { return null; } } /** * 用refreshToken生成新的accessToken和refreshToken * @param $refreshToken * @return bool * @throws HttpException */ public function refreshToken($refreshToken){ if(!$refreshToken){ return false; } $userId = Yii::$app->tokenRedis->hget($refreshToken, 'ID'); if(!$userId){ return false; } $userToken = AdminToken::findOne(['ADMIN_ID' => $userId]); $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'access', $userId); $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'refresh', $userId); return true; } /** * 用refreshToken生成新的accessToken * @param $refreshToken * @return bool * @throws HttpException */ public function refreshAccessToken($refreshToken){ if(!$refreshToken){ return false; } $userId = Yii::$app->tokenRedis->hget($refreshToken, 'ID'); if(!$userId){ return false; } $userToken = AdminToken::findOne(['ADMIN_ID' => $userId]); return $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'access', $userId); } /** * 用refreshToken生成新的refreshToken * @param $refreshToken * @return bool * @throws HttpException */ public function refreshRefreshToken($refreshToken){ if(!$refreshToken){ return false; } $userId = Yii::$app->tokenRedis->hget($refreshToken, 'ID'); if(!$userId){ return false; } $userToken = AdminToken::findOne(['ADMIN_ID' => $userId]); return $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'refresh', $userId); } /** * 更新token 的具体方法 * @param ActiveRecordInterface $userTokenModel * @param string $appType (pc|app) * @param string $typeToken * @param $userId * @return bool * @throws HttpException */ public function updateToken(ActiveRecordInterface $userTokenModel, $appType = Request::DEVICE_PC, $typeToken = 'access', $userId = 0){ $tokenField = strtoupper($appType.'_'.$typeToken.'_TOKEN'); $updateField = ''; $expiresIn = 0; if($appType === Request::DEVICE_PC){ if($typeToken === 'access'){ $updateField = 'PAT_UPDATED_AT'; $expiresIn = Yii::$app->params['backAccessTokenExpiresIn']; } elseif ($typeToken === 'refresh'){ $updateField = 'PRT_UPDATED_AT'; $expiresIn = Yii::$app->params['backRefreshTokenExpiresIn']; } else { throw new HttpException(500, 'token字段错误', 500); } } elseif ($appType === Request::DEVICE_APP){ if($typeToken === 'access'){ $updateField = 'AAT_UPDATED_AT'; $expiresIn = Yii::$app->params['backAccessTokenExpiresIn']; } elseif ($typeToken === 'refresh'){ $updateField = 'ART_UPDATED_AT'; $expiresIn = Yii::$app->params['backRefreshTokenExpiresIn']; } else { throw new HttpException(500, 'token字段错误', 500); } } // 老token $oldToken = $userTokenModel->$tokenField; // 生成 access_token /* @var $identityClass IdentityInterface */ $identityClass = $this->identityClass; $generateTokenMethodName = 'generate'.ucfirst($typeToken).'Token'; //$token = $identityClass::generateAccessToken(); $token = call_user_func([$identityClass, $generateTokenMethodName], $appType); $userTokenModel->$tokenField = $token; $userTokenModel->$updateField = Date::nowTime(); if(!$userTokenModel->save()){ throw new HttpException(500, 'token更新失败', 500); } // 查找TOKEN中是否有同一用户产生的垃圾token,有的话就清除 Yii::$app->tokenRedis->del($oldToken); $identity = $this->_apiIdentity; if(!$this->_apiIdentity){ if(!$userId){ throw new HttpException(500, 'userId不能为空', 500); } $identity = $identityClass::findIdentity($userId); } // 把 accessToken 当做key存入redis中内容为会员的ID和用户名 Yii::$app->tokenRedis->hset($token, 'ID', $identity['ID']); Yii::$app->tokenRedis->hset($token, 'ADMIN_NAME', $identity['ADMIN_NAME']); Yii::$app->tokenRedis->hset($token, 'ROLE_ID', $identity['ROLE_ID']); Yii::$app->tokenRedis->hset($token, 'TOKEN_UPDATED_AT', $userTokenModel->$updateField); Yii::$app->tokenRedis->expire($token, $expiresIn); $this->_token = array_merge($this->_token ? $this->_token : [], [ $typeToken.'Token' => $token, $typeToken.'TokenExpiresIn' => $expiresIn, $typeToken.'TokenUpdateAt' => $userTokenModel->$updateField, ]); return true; } /** * 获取管理员ID * @return int|null|string */ public function getId() { return $this->_userId; } /** * 获取token * @return null */ public function getToken(){ return $this->_token; } /** * 获取管理员信息 * @return null */ public function getUserInfo(){ return $this->_userInfo; } /** * 获取身份信息 * @param bool $autoRenew * @return null|IdentityInterface */ public function getIdentity($autoRenew = true) { if($this->_apiIdentity){ return $this->_apiIdentity; } else { if($this->_userId){ /* @var $class IdentityInterface */ $class = $this->identityClass; return $class::findOne(['ID' => $this->_userId]); } else { return null; } } } /** * 获取管理员权限 * @return mixed */ public function getAdminPermission(){ $userInfo = $this->_userInfo; $adminRoles = Cache::getAdminRole(); //$role = AdminRole::findOne(['ID'=>$userInfo['roleId']]); return $adminRoles[$userInfo['roleId']]['PERMISSION']; } /** * 校验管理员权限 * @param $controller * @param string $action * @return bool */ public function validateAdminAction($controller, $action = ''){ // 查看控制器是否在白名单中,如果在白名单中则直接返回true $noCheckActions = Yii::$app->params['noCheckPermissionActions']; if(in_array($controller.'/'.$action, $noCheckActions)){ return true; } $userInfo = $this->_userInfo; if($userInfo && $userInfo['roleId'] === Yii::$app->params['superAdminRoleId']){ return true; } // 获取管理员权限 $permission = $this->getAdminPermission(); if(!$permission){ return false; } if($controller && $action){ if(in_array($controller.'/'.$action, $permission)){ return true; } } // elseif ($controller){ // $pattern = '/'.$controller.'\//'; // foreach($permission as $value){ // if(preg_match($pattern, $value)){ // return true; // } // } // } return false; } /** * 查看是否有该控制器的权限 * @param $controller * @return bool */ public function validateAdminController($controller){ $userInfo = $this->_userInfo; if($userInfo && isset($userInfo) && $userInfo['roleId'] === Yii::$app->params['superAdminRoleId']){ return true; } $result = false; // 查看控制器是否在白名单中,如果在白名单中则直接返回true $noCheckActions = Yii::$app->params['noCheckPermissionActions']; foreach($noCheckActions as $action){ if(preg_match('/^'.$controller.'\//', $action)){ $result = true; break; } } // 查看会员的权限 $permissions = $this->getAdminPermission(); if($permissions){ foreach($permissions as $permission){ if(preg_match('/^'.$controller.'\//', $permission)){ $result = true; break; } } } return $result; } /** * 不需要检查管理员权限的控制器 * @param $controller * @return bool */ public function noCheckAdminController($controller){ $userInfo = $this->_userInfo; if($userInfo && isset($userInfo) && $userInfo['roleId'] === Yii::$app->params['superAdminRoleId']){ return false; } $result = false; // 查看控制器是否在白名单中,如果在白名单中则直接返回true $noCheckActions = Yii::$app->params['noCheckPermissionActions']; foreach($noCheckActions as $action){ if(preg_match('/^'.$controller.'\//', $action)){ $result = true; break; } } // 查看会员的权限 $permissions = $this->getAdminPermission(); if($permissions){ foreach($permissions as $permission){ if(preg_match('/^'.$controller.'\//', $permission)){ $result = false; break; } } } return $result; } }