_device = Yii::$app->request->getDevice(); } /** * 首次以用户名和密码的方式登录 * @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'], 'userName' => $identity['USER_NAME'], 'accessTokenUpdatedAt' => Date::nowTime(), 'ip' => $ip, ]; UserInfo::updateAll(['LAST_LOGIN_IP' => $ip, 'LAST_LOGIN_AT' => Date::nowTime()], 'USER_ID=:USER_ID', [':USER_ID'=>$identity['ID']]); $userToken = UserToken::findOne(['USER_ID' => $identity['ID']]); if (!$userToken) { $userToken = new UserToken(); $userToken->USER_ID = $identity['ID']; $userToken->CREATED_AT = Date::nowTime(); if (!$userToken->save()) { throw new HttpException(500, Form::formatErrorsForApi($userToken->getErrors()), 500); } } $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'access'); $this->updateToken($userToken, $appType = $this->_device, $typeToken = 'refresh'); //// Log::adminLoginInfo(); $this->afterLogin($identity, false, 0); } return !$this->getIsGuest(); } /** * 登录成功之后 * @param IdentityInterface $identity * @param bool $cookieBased * @param int $duration * @throws \yii\base\Exception */ public function afterLogin($identity, $cookieBased, $duration) { // 拉取站内信 Message::pullMsgByUser($identity['ID']); parent::afterLogin($identity, $cookieBased, $duration); } /** * 已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, 'userName' => Yii::$app->tokenRedis->hget($token, 'USER_NAME'), 'accessTokenUpdatedAt' => Yii::$app->tokenRedis->hget($token, 'TOKEN_UPDATED_AT'), 'ip' => Yii::$app->getRequest()->getUserIP(), ]; return $userId; } else { return null; } } /** * 从后台登录前台 * @param $userId * @return null * @throws HttpException */ public function loginByBackend($userId) { if (UserInfo::find()->where(['USER_ID' => $userId])->exists()) { $userToken = UserToken::findOne(['USER_ID' => $userId]); if (!$userToken) { $userToken = new UserToken(); $userToken->USER_ID = $userId; $userToken->CREATED_AT = Date::nowTime(); if (!$userToken->save()) { return null; } } self::$_isQuicklyLogin = true; $accessTokenResult = $this->updateToken($userToken, $appType = 'pc', $typeToken = 'access', $userId); $refreshTokenResult = $this->updateToken($userToken, $appType = 'pc', $typeToken = 'refresh', $userId); if ($accessTokenResult && $refreshTokenResult) { return $this->getToken(); } else { return null; } } 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 = UserToken::findOne(['USER_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 = UserToken::findOne(['USER_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 = UserToken::findOne(['USER_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['frontAccessTokenExpiresIn']; } elseif ($typeToken === 'refresh') { $updateField = 'PRT_UPDATED_AT'; $expiresIn = Yii::$app->params['frontRefreshTokenExpiresIn']; } else { throw new HttpException(500, 'token字段错误', 500); } } elseif ($appType === Request::DEVICE_APP) { if ($typeToken === 'access') { $updateField = 'AAT_UPDATED_AT'; $expiresIn = Yii::$app->params['frontAccessTokenExpiresIn']; } elseif ($typeToken === 'refresh') { $updateField = 'ART_UPDATED_AT'; $expiresIn = Yii::$app->params['frontRefreshTokenExpiresIn']; } 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, 'USER_NAME', $identity['USER_NAME']); Yii::$app->tokenRedis->hset($token, 'TOKEN_UPDATED_AT', $userTokenModel->$updateField); Yii::$app->tokenRedis->expire($token, $expiresIn); // 标记为快速登录的会员 if (self::$_isQuicklyLogin) { Yii::$app->redis->setex(Redis::key(\frontendApi\modules\v1\models\User::CACHE_IS_QUICKLY_LOGIN . $token), Yii::$app->params['frontAccessTokenExpiresIn'], 1); } $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 getUserPermission() { return []; } /** * 校验权限 * @param $controller * @param string $action * @return bool */ public function validateUserAction($controller, $action = '') { $isRecharge = \common\models\User::getEnCodeInfo($this->_userId)['IS_RECHARGE']; if($controller=='finance' && $action=='recharge' && $isRecharge==0){ return false; } return true; // $userInfo = $this->_userInfo; // if($userInfo['roleId'] === Yii::$app->params['superAdminRoleId']){ // return true; // } // // 查看控制器是否在白名单中,如果在白名单中则直接返回true // $noCheckActions = Yii::$app->params['noCheckPermissionActions']; // if(in_array($controller.'/'.$action, $noCheckActions)){ // return true; // } // return true; } /** * 查看是否有该控制器的权限 * @param $controller * @return bool */ public function validateUserController($controller) { $isAtlas = \common\models\User::getEnCodeInfo($this->_userId)['IS_ATLAS']; if($controller=='atlas' && $isAtlas==0){ return false; } return true; // if($userInfo['roleId'] === Yii::$app->params['superAdminRoleId']){ // return true; // } // $result = true; // // 查看控制器是否在白名单中,如果在白名单中则直接返回true // $noCheckActions = Yii::$app->params['noCheckPermissionActions']; // foreach($noCheckActions as $action){ // if(preg_match('/^'.$controller.'\//', $action)){ // $result = true; // break; // } // } // // return $result; } /** * 校验后台登录前台时所带的参数是否正确 * @return bool */ public function validateBackendAuth() { $data = []; $getData = \Yii::$app->getRequest()->get(); $postData = \Yii::$app->getRequest()->post(); $route = '/' . Yii::$app->controller->module->id . '/' . Yii::$app->controller->id . '/' . Yii::$app->controller->action->id; if (isset($getData[$route])) unset($getData[$route]); if (!empty($getData)) $data = array_merge($data, $getData); if (!empty($postData)) $data = array_merge($data, $postData); return (isset($data['signature']) && isset($data['timestamp']) && BackendToFrontendApi::checkSignature($data['signature'], $data)); } }