AccessTokenService.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. namespace services\api;
  3. use common\helpers\ApiCode;
  4. use common\helpers\ResultHelper;
  5. use common\models\user\User;
  6. use Yii;
  7. use yii\db\ActiveRecord;
  8. use yii\web\UnauthorizedHttpException;
  9. use yii\web\UnprocessableEntityHttpException;
  10. use common\enums\RedisKeyEnum;
  11. use common\helpers\ArrayHelper;
  12. use common\models\api\AccessToken;
  13. use common\components\Service;
  14. use common\enums\StatusEnum;
  15. /**
  16. *
  17. * Class AccessTokenService
  18. * @package services\api
  19. * @author qimall
  20. */
  21. class AccessTokenService extends Service
  22. {
  23. /**
  24. * 是否加入缓存
  25. *
  26. * @var bool
  27. */
  28. public $cache = false;
  29. /**
  30. * 缓存过期时间
  31. *
  32. * @var int
  33. */
  34. public $timeout;
  35. /**
  36. * 获取token
  37. *
  38. * @param User $user
  39. * @param $group
  40. * @param int $cycle_index 重新获取次数
  41. * @return array
  42. * @throws \yii\base\Exception
  43. */
  44. public function getAccessToken(User $user, $group, $cycle_index = 1)
  45. {
  46. $model = $this->findModel($user->id, $group);
  47. $model->user_id = $user->id;
  48. $model->group = $group;
  49. $is_multi_terminal_login = Yii::$app->services->setting->mall->get($user->mall_id, "user.is_multi_terminal_login");
  50. // 判断后台设置是否开启多端登录
  51. if (!$is_multi_terminal_login) {// 未开启多端缓存
  52. // 删除缓存
  53. !empty($model->access_token) && Yii::$app->cache->delete($this->getCacheKey($model->access_token));
  54. $model->refresh_token = Yii::$app->security->generateRandomString() . '_' . time();
  55. $model->access_token = Yii::$app->security->generateRandomString() . '_' . time();
  56. }
  57. // 字段不存在创建字段token
  58. if (!$model->access_token) {
  59. $model->refresh_token = Yii::$app->security->generateRandomString() . '_' . time();
  60. $model->access_token = Yii::$app->security->generateRandomString() . '_' . time();
  61. }
  62. // 判断缓存key是否还存在
  63. $cache = Yii::$app->cache->get($this->getCacheKey($model->access_token));
  64. if ($this->cache === true && !$cache) {
  65. $model->refresh_token = Yii::$app->security->generateRandomString() . '_' . time();
  66. $model->access_token = Yii::$app->security->generateRandomString() . '_' . time();
  67. }
  68. // 判断配置文件是否设置缓存验证
  69. if (Yii::$app->params['user.accessTokenValidity'] === true) {
  70. $expire = Yii::$app->params['user.accessTokenExpire'];
  71. $expire_timestamp = (int)substr($model->access_token, strrpos($model->access_token, '_') + 1) + $expire; //过期时间戳
  72. if ($expire_timestamp <= time()) {// 判断是否过期过期重新生成token
  73. $model ->refresh_token = Yii::$app->security->generateRandomString() . '_' . time();
  74. $model->access_token = Yii::$app->security->generateRandomString() . '_' . time();
  75. }
  76. }
  77. $model->status = StatusEnum::ENABLED;
  78. if (!$model->save()) {
  79. if ($cycle_index <= 3) {
  80. $cycle_index++;
  81. return self::getAccessToken($user, $group, $cycle_index);
  82. }
  83. throw new UnprocessableEntityHttpException('未知错误1');
  84. }
  85. $result = [];
  86. $result['access_token'] = $model->access_token;
  87. $user = ArrayHelper::toArray($user);
  88. unset($user['password'],$user['transaction_password'], $user['auth_key'], $user['password_reset_token'], $user['access_token'], $user['refresh_token']);
  89. // 写入缓存
  90. $this->cache === true && Yii::$app->cache->set($this->getCacheKey($model->access_token), $model, $this->timeout);
  91. return $result;
  92. }
  93. /**
  94. * @param $token
  95. * @param $type
  96. * @return array|mixed|null|ActiveRecord
  97. */
  98. public function getTokenToCache($token, $type, $cache = false)
  99. {
  100. if ($cache == false && $this->cache == false) {
  101. return $this->findByAccessToken($token);
  102. }
  103. $key = $this->getCacheKey($token);
  104. if (!($model = Yii::$app->cache->get($key))) {
  105. $model = $this->findByAccessToken($token);
  106. Yii::$app->cache->set($key, $model, $this->timeout);
  107. }
  108. return $model;
  109. }
  110. /**
  111. * 禁用token
  112. *
  113. * @param $access_token
  114. */
  115. public function disableByAccessToken($access_token)
  116. {
  117. $this->cache === true && Yii::$app->cache->delete($this->getCacheKey($access_token));
  118. if ($model = $this->findByAccessToken($access_token)) {
  119. $model->status = StatusEnum::DISABLED;
  120. return $model->save();
  121. }
  122. return false;
  123. }
  124. /**
  125. * 获取token
  126. *
  127. * @param $token
  128. * @return array|null|ActiveRecord|AccessToken
  129. */
  130. public function findByAccessToken($token)
  131. {
  132. return AccessToken::find()
  133. ->where(['access_token' => $token, 'status' => StatusEnum::ENABLED])
  134. ->one();
  135. }
  136. /**
  137. * @param $access_token
  138. * @return string
  139. */
  140. public function getCacheKey($access_token)
  141. {
  142. return RedisKeyEnum::suffix('apiAccessToken') . $access_token;
  143. }
  144. /**
  145. * 返回模型
  146. * @param $user_id
  147. * @param $group
  148. * @return array|AccessToken|ActiveRecord|null
  149. */
  150. protected function findModel($user_id, $group)
  151. {
  152. if (empty(($model = AccessToken::find()->where([
  153. 'user_id' => $user_id,
  154. 'group' => $group
  155. ])->one()))) {
  156. $model = new AccessToken();
  157. return $model->loadDefaultValues();
  158. }
  159. return $model;
  160. }
  161. /**
  162. * 获取用户token
  163. * @param $user
  164. * @param $group
  165. * @return array|mixed
  166. * @throws \yii\base\Exception
  167. */
  168. public function getUserToken($user,$group)
  169. {
  170. $user_token = AccessToken::find()->where([
  171. 'user_id' => $user->id,
  172. 'group' => $group,
  173. ])->one();
  174. $token = [];
  175. if($user_token){
  176. $token = $user_token->access_token;
  177. if (Yii::$app->params['user.accessTokenValidity'] === true) {
  178. $timestamp = (int)substr($token, strrpos($token, '_') + 1);
  179. $expire = Yii::$app->params['user.accessTokenExpire'];
  180. // 验证有效期
  181. if ($timestamp + $expire <= time()){
  182. $user_token = false;
  183. }
  184. }
  185. $token = ['access_token' => $token];
  186. }
  187. if(!$user_token || !$token){
  188. //重新生成
  189. $token = $this->getAccessToken($user,$group);
  190. }
  191. return $token;
  192. }
  193. /**
  194. * 删除某个站点的所有token缓存
  195. *
  196. * @param integer $mall_id
  197. * @param string $group
  198. * @return void
  199. */
  200. public function delAllCacheByMallId(int $mall_id, $group)
  201. {
  202. $query = User::find()->where(['mall_id' => $mall_id])->select('id');
  203. $user_ids = $query->column();
  204. foreach ($user_ids as $id) {
  205. $this->delCacheByUserId($id, $group);
  206. }
  207. AccessToken::deleteAll(['user_id' => $query]);
  208. }
  209. /**
  210. * 删除某个用户的token缓存
  211. *
  212. * @param integer $user_id
  213. * @param string $group
  214. * @return void
  215. */
  216. public function delCacheByUserId(int $user_id, $group)
  217. {
  218. $model = $this->findModel($user_id, $group);
  219. // 删除缓存
  220. !empty($model->access_token) && Yii::$app->cache->delete($this->getCacheKey($model->access_token));
  221. // $model->delete();
  222. }
  223. }