Controller.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * Controller is the customized base controller class.
  4. * All controller classes for this application should extend from this base class.
  5. */
  6. class Controller extends CController
  7. {
  8. /**
  9. * @var string the default layout for the controller view. Defaults to '//layouts/column1',
  10. * meaning using a single column layout. See 'protected/views/layouts/column1.php'.
  11. */
  12. public $layout='//layouts/column1';
  13. public array $authIds = [];
  14. public array $companyIds = [];
  15. public array $schoolIds = [];
  16. private int $_userId = 0;
  17. /**
  18. * 检查请求方是否合法
  19. * @return void
  20. * @throws CHttpException
  21. */
  22. public function checkRequest(): void
  23. {
  24. if (LWM_ENV == 'dev') {
  25. header("Access-Control-Allow-Origin: *");
  26. } else {
  27. if (!str_contains(Yii::app()->request->hostInfo, Yii::app()->params['url'])) {
  28. throw new CHttpException(403, '非法访问');
  29. }
  30. header("Access-Control-Allow-Origin:" . Yii::app()->request->hostInfo);
  31. }
  32. header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
  33. header("Access-Control-Allow-Headers: Content-Type, Authorization, Cookie");
  34. if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  35. exit(0); // 预检请求直接返回
  36. }
  37. }
  38. public function checkSign()
  39. {
  40. if (!\Yii::app()->request->isPostRequest || !empty($_FILES)) {
  41. return true;
  42. }
  43. if (!isset($_POST['sign'])) {
  44. return false;
  45. }
  46. if (!isset($_POST['timestamp']) || $_POST['timestamp'] < time() - 10) {
  47. return false;
  48. }
  49. $postSign = $_POST['sign'];
  50. unset($_POST['sign']); // 签名不计算sign
  51. $stringArray = []; // 对参与签名的参数进行排序
  52. foreach ($_POST as $k => $v) {
  53. if (is_array($v)) {
  54. $v = implode(',', $v);
  55. }
  56. $stringArray[] = $k . '=' . trim($v);
  57. }
  58. sort($stringArray, SORT_STRING);
  59. $query = implode('&', $stringArray);
  60. $sign = strtoupper(hash('sha256', $query . 'qwer'));
  61. if ($sign != $postSign) {
  62. Logger::errorMult($query, $sign);
  63. \CVarDumper::dump([$query, $sign, $postSign], 6, 1);die;
  64. }
  65. return $postSign == $sign;
  66. }
  67. /**
  68. * 限制操作频率
  69. * @param $second
  70. * @return void|null
  71. * @throws RedisException
  72. */
  73. public function dobuleCheck($second = 3)
  74. {
  75. $key = 'dobule_' . $this->_userId;
  76. if (!RedisInstance::getInstance()->setNx($key, 1, $second)) {
  77. return Helper::error('操作过于频繁');
  78. }
  79. }
  80. /**
  81. * @throws CHttpException
  82. */
  83. public function beforeAction($action): bool
  84. {
  85. $this->checkRequest();
  86. $token = $_SERVER['HTTP_AUTHORIZATION']?? '';
  87. $data = RedisInstance::getInstance()->get('user_token:'.$token);
  88. $this->_userId = $data['id']?? 0;
  89. Yii::app()->language = 'zh_cn';
  90. $controller = Yii::app()->controller->id;
  91. $action = $this->getAction()->getId();
  92. $path = strtolower($controller . '/'. $action);
  93. if( !in_array($controller, ['site'])
  94. &&!in_array($path, LewaimaiAdminPingtaiAuth::$noLoginRouters)
  95. && !$this->_userId
  96. ){
  97. Helper::error('请先登入', 401);
  98. }
  99. if (!$this->checkSign()) {
  100. Helper::error('签名错误', 402);
  101. }
  102. // 获取权限相关数据
  103. $this->_formatAuth();
  104. if (!LewaimaiAdminPingtaiAuth::adminAuth($controller, $action)
  105. && ($this->_userId && $this->_userId != 1)
  106. ) {
  107. Helper::error('您没有相应的权限');
  108. }
  109. return true;
  110. }
  111. private function _formatAuth(): void
  112. {
  113. $key = 'user_auth_' . $this->_userId;
  114. $data = RedisInstance::getInstance()->get($key);
  115. if (!$data) {
  116. $model = Useradmin::model()->findByPk($this->_userId);
  117. $authIds = DB::getScalerWithCriteria(
  118. 'role',
  119. DbCriteria::simpleCompare(['id' => $model->role_id])->setSelect('auth_ids')
  120. );
  121. $this->authIds = $authIds ? explode(',', $authIds) : [];
  122. $this->companyIds = $model->company_ids ? explode(',', $model->company_ids) : [];
  123. $this->schoolIds = $model->school_ids ? explode(',', $model->school_ids) : [];
  124. $json = json_encode([
  125. 'authIds' => $this->authIds,
  126. 'companyIds' => $this->companyIds,
  127. 'schoolIds' => $this->schoolIds,
  128. ]);
  129. RedisInstance::getInstance()->set($key, $json, 86400);
  130. } else {
  131. $data = json_decode($data, true);
  132. $this->authIds = $data['authIds'];
  133. $this->companyIds = $data['companyIds'];
  134. $this->schoolIds = $data['schoolIds'];
  135. }
  136. LewaimaiAdminPingtaiAuth::$authIds = $this->authIds;
  137. }
  138. public function clearAuth($id = 0)
  139. {
  140. $id = $id ? : $this->_userId;
  141. RedisInstance::getInstance()->delete('user_auth_' . $id);
  142. }
  143. public function getUserId()
  144. {
  145. return $this->_userId;
  146. }
  147. public function getSchoolFilter($filed = 'school_id'):?array
  148. {
  149. if ($this->_userId == 1 || in_array(-1, $this->companyIds)) {
  150. return null;
  151. }
  152. return $this->schoolIds;
  153. }
  154. public function checkSchoolId(int $id):bool
  155. {
  156. if ($this->_userId == 1 || in_array(-1, $this->schoolIds)) {
  157. return true;
  158. }
  159. return in_array($id, $this->schoolIds);
  160. }
  161. public function getCompanyFilter():?array
  162. {
  163. if ($this->_userId == 1 || in_array(-1, $this->companyIds)) {
  164. return null;
  165. }
  166. return $this->companyIds;
  167. }
  168. public function checkCompanyId(int $id):bool
  169. {
  170. if ($this->_userId == 1 || in_array(-1, $this->companyIds)) {
  171. return true;
  172. }
  173. return in_array($id, $this->companyIds);
  174. }
  175. }