Permissions.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: 中闽 < 1464674022@qq.com >
  5. * Date: 2019/12/5
  6. * Time: 17:44
  7. */
  8. namespace app\api\controller\base;
  9. use app\common\model\User;
  10. use Exception;
  11. use Firebase\JWT\JWT;
  12. use Firebase\JWT\Key;
  13. use think\exception\HttpResponseException;
  14. /**
  15. * 登入鉴权的接口父类
  16. * Class Permissions
  17. * @package app\api\controller\base
  18. */
  19. class Permissions extends Base
  20. {
  21. const JWT_COOKIE_NAME = 'x-token';
  22. const JWT_SESSION_NAME = 'user_info';
  23. private $userId;
  24. private $user;
  25. protected function _initialize()
  26. {
  27. parent::_initialize();
  28. //get token from header param body
  29. $jwt = $this->request->header('x-token', "");
  30. if (!$jwt) {
  31. $jwt = $this->request->param('x-token', "");
  32. if (!$jwt) {
  33. $callbackBody = file_get_contents('php://input');
  34. if (!$callbackBody) {
  35. $this->json_error('请先登入', null, self::ERR_CODE_LOGIN);
  36. }
  37. $callbackJson = json_decode($callbackBody, true);
  38. $jwt = isset($callbackJson['x-token']) ? $callbackJson['x-token'] : '';
  39. if (!$jwt) {
  40. $this->json_error('请先登入', null, self::ERR_CODE_LOGIN);
  41. }
  42. }
  43. }
  44. //check x-token
  45. try {
  46. JWT::$leeway = 60;
  47. $jwt_key = system_salt();
  48. $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));
  49. $arr = (array)$decoded;
  50. if (!isset($arr['exp']) || $arr['exp'] < time()) {
  51. self::clear_session();
  52. throw new \think\Exception('登入超时,请重新登录');
  53. } else {
  54. //鉴权成功
  55. $this->userId = $arr['data']->userId;
  56. $loginTime = $arr['data']->loginTime;
  57. $exptime = $arr['exp'];
  58. //限制账号多次登入
  59. // if ($this->getUser()->getData('login_time') > $loginTime) {
  60. // $this->clear_session();
  61. // throw new \think\Exception('您的账号已经在其它地方登入');
  62. // }
  63. // 每次刷新jwt,loginTime要保持不变
  64. self::createJwt($this->userId, $loginTime, 3600, $exptime);
  65. return;
  66. }
  67. } catch (Exception $e) {
  68. if ($e instanceof HttpResponseException) {
  69. $this->json_error($e->getResponse()->getData()['msg']);
  70. }
  71. switch ($e->getMessage()) {
  72. case "Expired token":
  73. self::clear_session();
  74. $this->json_error('登入超时,请重新登录', null, self::ERR_CODE_LOGIN);
  75. break;
  76. case "Wrong number of segments":
  77. self::clear_session();
  78. $this->json_error('Token验证失败,请重新登录', null, self::ERR_CODE_LOGIN);
  79. break;
  80. default:
  81. $msg = "error:" . $e->getMessage();
  82. $this->json_error($msg);
  83. }
  84. }
  85. }
  86. /**
  87. * 获取登入token,并设置登入状态
  88. * @param $userId int 用户id
  89. * @param $loginTime int 用户登入时间
  90. * @param int $expire 设置jwt过期时间,从当前时间开始计算
  91. * @param null $exp 强制指定过期时间,用来刷新jwt
  92. * @return string
  93. */
  94. public static function createJwt($userId, $loginTime, $expire = 3600, $exp = null)
  95. {
  96. $nowtime = time();
  97. $exptime = $exp ? $exp : $nowtime + $expire;
  98. //添加 exptime,后端可以判断过期并退出, 不通过session
  99. $data = ['userId' => $userId, 'loginTime' => $loginTime, 'exptime' => $exptime];
  100. $token = [
  101. 'iss' => PRODUCT_URL, //签发者
  102. 'aud' => PRODUCT_URL, //jwt所面向的用户
  103. 'iat' => $nowtime, //签发时间
  104. 'nbf' => $nowtime + 10, //在什么时间之后该jwt才可用
  105. 'exp' => $exptime, //过期时间
  106. 'data' => $data //不要存放隐私信息,jwt可以保证内容不被修改,但可以被解码查看内容
  107. ];
  108. // 得到jwt
  109. $jwt_key = system_salt();
  110. $jwt = JWT::encode($token, $jwt_key, 'HS256');
  111. //设置登入状态
  112. session(self::JWT_SESSION_NAME, $data);
  113. cookie(self::JWT_COOKIE_NAME, $jwt, 3600 * 12);
  114. return $jwt;
  115. }
  116. /**
  117. * 获取user对象
  118. * @return null|User
  119. */
  120. protected function getUser()
  121. {
  122. if (!$this->user) {
  123. $user = User::get($this->userId);
  124. if (!$user) {
  125. $this->json_error('找不到用户信息,请重新登入', null, self::ERR_CODE_LOGIN);
  126. }
  127. $this->user = $user;
  128. }
  129. return $this->user;
  130. }
  131. /**
  132. * 获取userid
  133. * @return null
  134. */
  135. protected function getUserId()
  136. {
  137. return $this->userId;
  138. }
  139. /**
  140. * 退出登入状态
  141. */
  142. public static function clear_session()
  143. {
  144. cookie(self::JWT_COOKIE_NAME, null);
  145. session(self::JWT_SESSION_NAME, null);
  146. }
  147. }