| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- <?php
- /**
- * The zen file of sso module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
- * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Yidong Wang <yidong@easycorp.ltd>
- * @package sso
- * @link https://www.zentao.net
- */
- class ssoZen extends sso
- {
- /**
- * Get feishu accessToken.
- *
- * @param object $appConfig
- * @access protected
- * @return array
- */
- protected function getFeishuAccessToken($appConfig)
- {
- $appUrl = $this->config->sso->feishuAppInfoAPI;
- $appParams = array('app_id' => $appConfig->appId, 'app_secret' => $appConfig->appSecret);
- $appResult = common::http($appUrl, $appParams, array(), array(), 'json');
- if(empty($appResult)) return array('result' => 'fail', 'message' => $this->lang->sso->feishuResponseEmpty);
- $appInfo = json_decode($appResult);
- if(!isset($appInfo->msg) || $appInfo->msg != 'ok') return array('result' => 'fail', 'message' => $appResult);
- return array('result' => 'success', 'token' => $appInfo->app_access_token);
- }
- /**
- * Get feishu userToken.
- *
- * @param string $code
- * @param string $accessToken
- * @access protected
- * @return array
- */
- protected function getFeishuUserToken($code, $accessToken)
- {
- $tokenUrl = $this->config->sso->feishuTokenAPI;
- $tokenHeaders = array('Authorization: Bearer ' . $accessToken);
- $tokenParams = array('grant_type' => 'authorization_code', 'code' => $code);
- $tokenResult = common::http($tokenUrl, $tokenParams, array(), $tokenHeaders, 'json');
- if(empty($tokenResult)) return array('result' => 'fail', 'message' => $this->lang->sso->feishuResponseEmpty);
- $tokenInfo = json_decode($tokenResult);
- if(!isset($tokenInfo->msg) or $tokenInfo->msg != 'success') return array('result' => 'fail', 'message' => $tokenResult);
- return array('result' => 'success', 'token' => $tokenInfo->data->access_token);
- }
- /**
- * Get bind feishu user.
- *
- * @param string $userToken
- * @param object $feishuConfig
- * @access protected
- * @return array
- */
- protected function getBindFeishuUser($userToken, $feishuConfig)
- {
- $userUrl = $this->config->sso->feishuUserInfoAPI;
- $userHeaders = array('Authorization: Bearer ' . $userToken);
- $userResult = common::http($userUrl, array(), array(), $userHeaders, 'json');
- if(empty($userResult)) return array('result' => 'fail', 'message' => $this->lang->sso->feishuResponseEmpty);
- $userInfo = json_decode($userResult);
- if(!isset($userInfo->msg) or $userInfo->msg != 'success') return array('result' => 'fail', 'message' => $userResult);
- $openID = $userInfo->data->open_id;
- /* Get the user relationship bound in webhook. */
- $account = $this->loadModel('webhook')->getBindAccount($feishuConfig->id, 'webhook', $openID);
- if(empty($account)) return array('result' => 'fail', 'message' => $this->lang->sso->unbound);
- $user = $this->loadModel('user')->getById($account);
- return array('result' => 'success', 'user' => $user);
- }
- /**
- * Build user data for createUser method.
- *
- * @access protected
- * @return object
- */
- protected function buildUserForCreate()
- {
- return form::data($this->config->sso->form->createUser)->setDefault('ranzhi', $this->post->account)->get();
- }
- /**
- * Idenfy from SSO.
- *
- * @param string $locate
- * @access protected
- * @return bool
- */
- protected function idenfyFromSSO($locate)
- {
- if($this->get->status != 'success' || md5($this->get->data) != $this->get->md5) return false;
- $userIP = helper::getRemoteIp();
- $last = $this->server->request_time;
- $data = json_decode(base64_decode($this->get->data));
- if($data->auth != $this->computeAuth($data->token)) return false;
- $user = $this->sso->getBindUser($data->account);
- if(!$user)
- {
- $this->session->set('ssoData', $data);
- return $this->locate($this->createLink('sso', 'bind', "referer=" . helper::safe64Encode($locate)));
- }
- if($this->loadModel('user')->isLogon() and $this->session->user->account == $user->account) return $this->locate($locate);
- $user->last = date(DT_DATETIME1, (int)$last);
- $user->lastTime = $user->last;
- $user = $this->user->checkNeedModifyPassword($user, 0);
- $this->dao->update(TABLE_USER)->set('visits = visits + 1')->set('ip')->eq($userIP)->set('last')->eq($last)->where('account')->eq($user->account)->exec();
- $this->user->login($user);
- return $this->locate($locate);
- }
- /**
- * Locate notify link.
- *
- * @param string $location
- * @param string $referer
- * @access protected
- * @return void
- */
- protected function locateNotifyLink($location, $referer)
- {
- $isGet = strpos($location, '&') !== false;
- $requestType = $this->get->requestType;
- if(isset($requestType)) $isGet = $requestType == 'GET' ? true : false;
- if($isGet) $location = $this->buildLocationByGET($location, $referer);
- if(!$isGet) $location = $this->buildLocationByPATHINFO($location, $referer);
- if(!empty($_GET['sessionid']))
- {
- $sessionConfig = json_decode(base64_decode($this->get->sessionid), false);
- $location .= '&' . $sessionConfig->session_name . '=' . $sessionConfig->session_id;
- }
- $this->locate($location);
- }
- /**
- * Build location by GET.
- *
- * @param string $location
- * @param string $referer
- * @access private
- * @return string
- */
- private function buildLocationByGET($location, $referer)
- {
- if(strpos($location, '&') === false)
- {
- $position = strrpos($location, '/') + 1;
- $uri = substr($location, 0 ,$position);
- $param = str_replace('.html', '', substr($location, $position));
- list($module, $method) = explode('-', $param);
- $location = $uri . 'index.php?m=' . $module . '&f=' . $method;
- }
- return rtrim($location, '&') . '&' . $this->buildSSOParams($referer);
- }
- /**
- * Build location by PATH_INFO.
- *
- * @param string $location
- * @param string $referer
- * @access private
- * @return string
- */
- private function buildLocationByPATHINFO($location, $referer)
- {
- if(strpos($location, '&') !== false)
- {
- list($uri, $param) = explode('index.php', $location);
- $param = substr($param, 1);
- parse_str($param, $result);
- $location = $uri . $result['m'] . '-' . $result['f'] . '.html';
- }
- return rtrim($location, '?') . '?' . $this->buildSSOParams($referer);
- }
- /**
- * Build SSO params.
- *
- * @param string $referer
- * @access private
- * @return string
- */
- private function buildSSOParams($referer)
- {
- $userIP = helper::getRemoteIp();
- $token = $this->get->token;
- $auth = $this->computeAuth($token);
- $callback = urlencode(common::getSysURL() . inlink('login', "type=return"));
- return "token=$token&auth=$auth&userIP=$userIP&callback=$callback&referer=$referer";
- }
- /**
- * Compute auth.
- *
- * @access private
- * @return string
- * @param string $token
- */
- private function computeAuth($token)
- {
- $userIP = helper::getRemoteIp();
- $code = $this->config->sso->code;
- $key = $this->config->sso->key;
- return md5($code . $userIP . $token . $key);
- }
- }
|