response = $response; // } public function login(Jwt $jwt) { $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'username' => 'required', 'password' => 'required', 'type' => 'required', // 'code' => 'required', ], [ 'username.required' => '用户名不能为空', 'password.required' => '密码不能为空', 'type.required' => '登录方式必填', // 'code.required' => 'code方式必填', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } // $comm = new CommonService(); // $redis = $this->container->get(\Hyperf\Redis\Redis::class); // $code = $redis->get($reqData['code']); // if (empty($code)) { // return Result::error("验证码已过期"); // } // if (strtolower($code) != strtolower($reqData['captcha'])) { // return Result::error("验证码错误"); // } $where = []; if ($reqData['type'] == 1) { //密码登录 $where = [ 'user_name' => $reqData['username'], ]; } $userInfos = $this->userServiceClient->verifyUserInfo($where); if ($userInfos['code'] == 0) { return Result::error("用户不存在"); } if($userInfos['data']['status']==0){ return Result::error("用户已经冻结"); } if (md5(md5($reqData['password']) . $userInfos['data']['salt']) != $userInfos['data']['password']) { return Result::error("登陆密码错误"); } if($userInfos['data']['type_id']!=10000){ $authData = [ 'id'=>$userInfos['data']['sszq'], 'SiteId'=>Context::get("SiteId") ]; var_dump("参数:",$authData); $resultAuth = $this->checkUserAuth($authData); if(!$resultAuth){ return Result::error("您没有权限登陆此网站"); } } $userData = [ 'uid' => $userInfos['data']['id'], // 如果使用单点登录,必须存在配置文件中的sso_key的值,一般设置为用户的id 'user_name' => $userInfos['data']['user_name'], 'mobile' => $userInfos['data']['mobile'], 'email' => $userInfos['data']['email'], 'level_id' => $userInfos['data']['level_id'], 'type_id' => $userInfos['data']['type_id'], ]; // 使用默认场景登录 $token = $jwt->getToken('default', $userData); // 检查是否有旧的token $old_token = UserToken::where('user_id', $userData['uid'])->first(); if (!empty($old_token)) { $jwt->logout($old_token->token); try { $jwt->verifyToken($old_token->token); }catch (\Exception $exception){ $code = $exception->getCode(); if ($code== 400) { $new_token = UserToken::where('user_id', $userData['uid'])->update(['token' => $token->toString()]); if (empty($new_token)) { return Result::error("Token过期失败!"); } } else{ return Result::error("Token过期失败!"); } } }else{ $usernew_token = $token->toString(); $user_token = UserToken::create([ 'user_id' => $userData['uid'], 'token' => $usernew_token ]); if (empty($user_token)) { return Result::error("登录失败!"); } } $data = [ 'token' => $token->toString(), 'exp' => $jwt->getTTL($token->toString()), ]; return Result::success($data); } /** * @return void */ public function checkVerifyCode(Jwt $jwt) { //其它信息暂时不管 先以openid $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'token' => 'required', ], [ 'token.required' => 'token不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $userInfo = $jwt->getClaimsByToken($reqData['token']); if ($userInfo) { return Result::success(['token' => $reqData['token']]); } else { return Result::error("token无效"); } } /** * 注册或登陆 * @return void */ public function registerOrLogin(Jwt $jwt) { //获取access_token $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'code' => 'required', ], [ 'code.required' => 'code不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $url = env("WECHAT") . "cgi-bin/token?appid=" . env("APPID") . "&secret=" . env("APP_SECRET") . "&grant_type=client_credential"; $result = PublicData::http_get($url); $accessTokenData = json_decode($result, true); //获取openid $url = env("WECHAT") . "sns/jscode2session?appid=" . env("APPID") . "&secret=" . env("APP_SECRET") . "&js_code=" . $reqData['loginCode'] . "&grant_type=authorization_code"; $result = PublicData::http_get($url); $openInfoData = json_decode($result, true); if (isset($openInfoData['errcode']) && in_array($openInfoData['errcode'], [40163, 40029])) { return Result::error($openInfoData['errmsg']); } $data = [ 'code' => $reqData['code'], 'openid' => $openInfoData['openid'], ]; // 将数组转换为JSON字符串 $jsonData = json_encode($data); // 初始化cURL会话 $ch = curl_init(env("WECHAT") . "wxa/business/getuserphonenumber?access_token=" . $accessTokenData['access_token']); // 设置cURL选项 Todo 这里有一万个wc 封装成post方法就报错,后期再研究 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen($jsonData), ]); // 执行cURL会话 $response = curl_exec($ch); // 检查是否有错误发生 if (curl_errno($ch)) { return Result::error("获取手机号失败"); } // 关闭cURL会话 curl_close($ch); $response = json_decode($response, true); if ($response['errcode'] == '40029') { return Result::error($openInfoData['errmsg']); } // 打印响应内容 var_dump($openInfoData, $response); //根据openid 获取token $checkUserInfo = $this->userServiceClient->verifyUserInfo([ 'user_name' => $response['phone_info']['purePhoneNumber'], ]); if ($checkUserInfo['code'] == 0) { $salt = rand(1, 999999); $createUserData = [ 'user_name' => $response['phone_info']['purePhoneNumber'], 'salt' => $salt, 'password' => $openInfoData['openid'], 'type_id' => 20000, ]; $checkUserInfo = $this->userServiceClient->createUser($createUserData); } //根据openid和手机号判断是否注册,未注册直接注册 $wechatReqData = [ 'openid' => $openInfoData['openid'], 'purePhoneNumber' => $response['phone_info']['purePhoneNumber'], ]; $wechatInfo = $this->userServiceClient->getWechatInfo($wechatReqData); if ($wechatInfo['code'] == 0) { $wechatData = [ 'openid' => $openInfoData['openid'], 'phoneNumber' => $response['phone_info']['phoneNumber'], 'purePhoneNumber' => $response['phone_info']['purePhoneNumber'], 'countryCode' => $response['phone_info']['countryCode'], 'watermark' => json_encode($response['phone_info']['watermark']), 'user_id' => $checkUserInfo['data']['id'], ]; $this->userServiceClient->addWechatInfo($wechatData); } var_dump($checkUserInfo); $userData = [ 'uid' => $checkUserInfo['data']['id'], // 如果使用单点登录,必须存在配置文件中的sso_key的值,一般设置为用户的id 'user_name' => $response['phone_info']['phoneNumber'], 'mobile' => $checkUserInfo['data']['mobile'] ?? '', 'email' => $checkUserInfo['data']['email'], // 'rong_token' => $userInfos['data']['rong_token'], 'level_id' => $checkUserInfo['data']['level_id'], 'type_id' => $checkUserInfo['data']['type_id'], ]; // 使用默认场景登录 $token = $jwt->getToken('default', $userData); $data = [ 'token' => $token->toString(), 'exp' => $jwt->getTTL($token->toString()), ]; return Result::success($data); } public function getToken(JWT $jwt) { $reqData = $this->request->all(); $userInfos = $this->userServiceClient->getUserInfo((int) $reqData['id']); $userData = [ 'uid' => $userInfos['data']['id'], // 如果使用单点登录,必须存在配置文件中的sso_key的值,一般设置为用户的id 'user_name' => $userInfos['data']['user_name'], 'mobile' => $userInfos['data']['mobile'], 'email' => $userInfos['data']['email'], 'level_id' => $userInfos['data']['level_id'], 'type_id' => $userInfos['data']['type_id'], ]; var_dump($userInfos); // 使用默认场景登录 $token = $jwt->getToken('default', $userData); return Result::success($token->toString()); } public function httpPost() { } # http头部必须携带token才能访问的路由 public function getData(Jwt $jwt) { // var_dump($this->UserId); $h = $this->request->getHeaders(); // var_dump($this->request->getHeaders()); // $a= 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwaHBlcjY2Ni9qd3QiLCJ1aWQiOjMyLCJ1c2VyX25hbWUiOiIxIiwicm9sZV9pZCI6MSwibW9iaWxlIjoiMTU4MDEyNDU3NTUiLCJlbWFpbCI6IjVAcXEuY29tIiwicm9uZ190b2tlbiI6IiIsImxldmVsX2lkIjo4LCJqd3Rfc2NlbmUiOiJkZWZhdWx0IiwianRpIjoiZGVmYXVsdF82Njc1MjJkZDQ3YWYxMi41MTE5MjI5MiIsImlhdCI6MTcxODk1MjY2OSwibmJmIjoxNzE4OTUyNjY5LCJleHAiOjE3MjE1NDQ2Njl9.e0JW8fgNrwBdFgmQ8GNtES2ME1SbcbIih5MsQWzT6sk'; $arr = $jwt->getClaimsByToken($h['token'][0]); var_dump($h['token'][0], "+++++++++++", $arr, "===####"); return $this->response->json(['code' => 0, 'msg' => 'success', 'data' => ['a' => 1]]); } /** * 检测用户权限 * @return void */ public function checkUserAuth($data) { $websiteGroup = [ 'id'=>$data['id'] ]; $result = $this->userServiceClient->getWebsiteGroupInfo($websiteGroup); if($result['code']==200){ if($data['SiteId'] && $result['data']['web_ids']){ if(in_array($data['SiteId'],json_decode($result['data']['web_ids'],true))){ return true; } }else{ return false; } } } /** * 查询登陆状态 * @return array * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface * @throws \RedisException */ public function loginStatus(Jwt $jwt) { $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'token' => 'required', ], [ 'token.required' => 'token不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } try { $status = $jwt->verifyToken($reqData['token']); // var_dump("状态:",$status); return Result::success(['isLogin' => true]); }catch(\Exception $e){ return Result::error('token已过期:'.$e->getMessage()); } } /** *登陆 * @return void */ public function loginapi() { $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'token' => 'required', ], [ 'token.required' => 'token不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $redis = $this->container->get(\Hyperf\Redis\Redis::class); $ticket = md5($reqData['token']); $res = $redis->set('ticket:' . $ticket, $reqData['token'], 3600*24); if ($res){ return Result::success(['ticket' => $ticket ,'isSave' => 1]); } else { return Result::error('存储失败'); } } public function logoutapi(Jwt $jwt) { $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'token' => 'required', ], [ 'token.required' => 'token不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $redis = $this->container->get(\Hyperf\Redis\Redis::class); $ticket = md5($reqData['token']); $isDel = 0; if ($redis->exists('ticket:' . $ticket)) { $res = $redis->del('ticket:' . $ticket); if (!!$res && $res == 1) $isDel = 1; }else{ $isDel = 1; } try { $jwt->logout($reqData['token']); }catch (\Exception $e){ return Result::success(['isDel' => $isDel]); } return Result::success(['isDel' => $isDel]); } public function goLogin() { // 获取请求数据并设置默认值 $reqData = $this->request->all(); // 安全过滤 Admin-Token 和 ticket $cookieList = $this->request->getCookieParams(); // 安全过滤 Admin-Token 和 ticket $adminToken = !empty($cookieList['Admin-Token']) ? $this->sanitizeInput($cookieList['Admin-Token']) : ''; $ticket = !empty($reqData['ticket']) ? $this->sanitizeInput($reqData['ticket']) : ''; $backurl = $this->sanitizeBackUrl($reqData['backurl'] ?? $_SERVER['HTTP_REFERER'] ?? ''); // 校验 THE_HOST 环境变量 $theHost = env("THE_HOST"); if (empty($theHost)) { return Result::error('系统配置错误:THE_HOST 未定义'); } var_dump("admintoken:",$adminToken); // 如果存在 adminToken,则进行登录校验 if (!empty($adminToken)) { // 处理登录 $redis = $this->container->get(\Hyperf\Redis\Redis::class); var_dump("ticket1111:",$ticket); if(!empty($ticket)){ if (!empty($ticket) && $redis->exists('ticket:' . $ticket)) { $backurl = rtrim($backurl, '/'); return $this->response->redirect($this->fun_http($backurl . '?ticket=' . $ticket . '&admintoken=' . urlencode($adminToken)), 302); }else{ var_dump("222222222:"); return $this->response->redirect($this->fun_http('http://'.$theHost.'/#/login?backurl='.urlencode($backurl)), 302); } }else{ $ticket = md5($adminToken); } var_dump("333333333333333:"); return $this->response->redirect($this->fun_http($backurl . '?ticket=' . $ticket . '&admintoken=' . urlencode($adminToken)), 302); }else{ var_dump("444444444444444:"); return $this->response->redirect($this->fun_http('http://'.$theHost.'/#/login?backurl='.urlencode($backurl)), 302); } } /** * 安全过滤输入数据 * @param string $input * @return string */ private function sanitizeInput(string $input): string { return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8'); } /** * 校验并清理 backurl * @param string $backurl * @return string */ private function sanitizeBackUrl(string $backurl): string { // 解码并去除多余字符 $decodedUrl = urldecode($backurl); return filter_var($decodedUrl, FILTER_VALIDATE_URL) ?: ''; } /** * 跳转到目标页面 * @param string $backurl * @param string $ticket * @param string $adminToken */ private function redirectWithTicket(string $backurl, string $ticket, string $adminToken) { $backurl = rtrim($backurl, '/'); $redirectUrl = $this->fun_http($backurl . '?ticket=' . $ticket . '&admintoken=' . urlencode($adminToken)); // $loginUrl = 'http://' . $theHost . '/#/login?backurl=' . urlencode($backurl); // return $this->response->redirect($loginUrl, 302); return $this->response->redirect($redirectUrl, 302); } /** * 处理 URL * @param string $url * @return string */ private function fun_http(string $url): string { // 确保 URL 以 http 或 https 开头 if (!preg_match('/^https?:\/\//i', $url)) { $url = 'http://' . $url; } return $url; } /** * 退出 * @return void */ public function logout(Jwt $jwt) { $reqData = $this->request->all(); $validator = $this->validationFactory->make( $reqData, [ 'backurl' => 'required', 'admintoken' => 'required', ], [ 'backurl.required' => 'backurl不能为空', 'admintoken.required' => 'admintoken不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $redis = $this->container->get(\Hyperf\Redis\Redis::class); $ticket = md5($reqData['admintoken']); $res = $redis->del('ticket:' . $ticket); var_dump("删除redis:", $res); var_dump("获取redis:", $redis->get('ticket:' . $ticket)); // 获取所有 Cookie $cookies = $this->request->getCookieParams(); var_dump("获取cookie:", $cookies); if($cookies){ foreach ($cookies as $name => $value) { if($name){ $expire = time() - 3600; // 设置过期时间为过去的时间 $cookie = new Cookie((string)$name, '', $expire, '/'); $this->response = $this->response->withCookie($cookie); } } } try { $jwt->logout($reqData['admintoken']); } catch (\Exception $e) { var_dump("返回错误信息:", $e->getMessage()); } $backurl = $this->fun_http($reqData['backurl']); var_dump("返回地址:", $backurl); return $this->response->redirect($backurl, 302); } /** * 登录回调 * @return void */ public function backlogin() { $reqData = $this->request->all(); var_dump("===============接收参数:",$reqData); $validator = $this->validationFactory->make( $reqData, [ 'backurl' => 'required', 'token' => 'required', ], [ 'backurl.required' => 'backurl不能为空', 'token.required' => 'token不能为空', ] ); if ($validator->fails()) { $errorMessage = $validator->errors()->first(); return Result::error($errorMessage); } $redis = $this->container->get(\Hyperf\Redis\Redis::class); $ticket = md5($reqData['token']); $res = $redis->set('ticket:' . $ticket, $reqData['token'], 3600*24); var_dump("===============返回值:",$res); $expire = time()+3600*24; $cookieName = 'Admin-Token'; // 创建 Cookie 实例 $cookie = new Cookie($cookieName, $reqData['token'], $expire, '/'); // 清空 Cookie $r = $this->response = $this->response->withCookie($cookie); var_dump("设置token:", $r); if($res && !empty($ticket)){ $url = $reqData['backurl'] . '/?ticket=' . $ticket . '&admintoken=' . urlencode($reqData['token']); $url = $this->fun_http($url); var_dump("跳转地址gogo:",$url); return $this->response->redirect($url, 302); } } }