request = is_null($request) ? Request::instance() : $request; // 控制器初始化 $this->_initialize(); } /** * 初始化操作 * @access protected */ protected function _initialize() { //跨域请求检测 check_cors_request(); // 检测IP是否允许 check_ip_allowed(); //移除HTML标签 $this->request->filter('trim,strip_tags,htmlspecialchars'); // token $token = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token'))); if (!$this->match($this->noNeedLogin)) { $this->init($token); } else { if ($token) { $this->init($token); } } return true; } /** * 检测当前控制器和方法是否匹配传递的数组 * * @param array $arr 需要验证权限的数组 * @return boolean */ public function match($arr = []) { $request = Request::instance(); $arr = is_array($arr) ? $arr : explode(',', $arr); if (!$arr) { return false; } $arr = array_map('strtolower', $arr); // 是否存在 if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) { return true; } // 没找到匹配 return false; } /** * 操作成功返回的数据 * @param string $msg 提示信息 * @param mixed $data 要返回的数据 * @param int $code 错误码,默认为1 * @param string $type 输出类型 * @param array $header 发送的 Header 信息 */ protected function success($msg = '', $data = null, $code = 1, $type = null, array $header = []) { $this->result($msg, $data, $code, $type, $header); } /** * 操作失败返回的数据 * @param string $msg 提示信息 * @param mixed $data 要返回的数据 * @param int $code 错误码,默认为0 * @param string $type 输出类型 * @param array $header 发送的 Header 信息 */ protected function error($msg = '', $data = null, $code = 0, $type = null, array $header = []) { $this->result($msg, $data, $code, $type, $header); } /** * 返回封装后的 API 数据到客户端 * @access protected * @param mixed $msg 提示信息 * @param mixed $data 要返回的数据 * @param int $code 错误码,默认为0 * @param string $type 输出类型,支持json/xml/jsonp * @param array $header 发送的 Header 信息 * @return void * @throws HttpResponseException */ protected function result($msg, $data = null, $code = 0, $type = null, array $header = []) { $result = [ 'code' => $code, 'msg' => $msg, 'time' => Request::instance()->server('REQUEST_TIME'), 'data' => $data, ]; // 如果未设置类型则使用默认类型判断 $type = $type ? : $this->responseType; if (isset($header['statuscode'])) { $code = $header['statuscode']; unset($header['statuscode']); } else { //未设置状态码,根据code值判断 $code = $code >= 1000 || $code < 200 ? 200 : $code; } $response = Response::create($result, $type, $code)->header($header); throw new HttpResponseException($response); } /** * 师傅登录 * @param int $id * @return bool */ public function workerLogin(int $id): bool { $user = $this->getWorkerModel()->find($id); $this->tryLogin($user); $user = $user->toArray(); $user['token'] = $this->getTokenByUserId($user['id']); $this->user = $user; return true; } public function workerLogout(): bool { if ($this->token) { Token::delete($this->token); } return true; } /** * 验证数据 * @access protected * @param array $data 数据 * @param string|array $validate 验证器名或者验证规则数组 * @param array $message 提示信息 * @param bool $batch 是否批量验证 * @param mixed $callback 回调方法(闭包) * @return array|string|true * @throws ValidateException */ public function validate($data, $validate, $messageHeader = '', $message = [], $batch = false, $callback = null) { if (is_array($validate)) { $v = Loader::validate(); $v->rule($validate); } else { // 支持场景 if (strpos($validate, '.')) { list($validate, $scene) = explode('.', $validate); } $v = Loader::validate($validate); !empty($scene) && $v->scene($scene); } // 批量验证 if ($batch || $this->batchValidate) { $v->batch(true); } // 设置错误信息 if (is_array($message)) { $v->message($message); } // 使用回调验证 if ($callback && is_callable($callback)) { call_user_func_array($callback, [$v, &$data]); } if (!$v->check($data)) { $errorMessage = $v->getError(); if ($messageHeader) { $errorMessage = "$messageHeader$errorMessage"; } if ($this->failException) { throw new ValidateException($errorMessage); } throw new ApiException($errorMessage); } return true; } private function init($token) { if ($this->user) { return true; } $data = Token::get($token); if (!$data) { throw new ApiException('登录已失效', 401); } $this->token = $token; $user = $this->getWorkerModel() ->field($this->allowFields) ->where('id', $data['user_id']) ->find(); $this->tryLogin($user); $this->user = $user->toArray(); return true; } private function tryLogin($user) { if (!$user) { throw new ApiException('用户不存在,请联系平台'); } if ($user->status === 0) { throw new ApiException('当前账号不可用'); } return true; } protected function getTokenByUserId($userId) { $token = Random::uuid(); Token::set($token, $userId, $this->keeptime); return $token; } }