Permissions.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 = config('JWT_KEY');
  48. $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));
  49. $arr = (array)$decoded;
  50. if (!isset($arr['exp']) || $arr['exp'] < time()) {
  51. throw new \think\Exception('Expired token');
  52. } else {
  53. //鉴权成功
  54. $this->userId = $arr['data']->userId;
  55. $loginTime = $arr['data']->loginTime;
  56. $exptime = $arr['exp'];
  57. // 每次刷新jwt,loginTime要保持不变
  58. self::createJwt($this->userId, $loginTime, 3600, $exptime);
  59. return;
  60. }
  61. } catch (Exception $e) {
  62. // if ($e instanceof HttpResponseException) {
  63. // $this->json_error($e->getResponse()->getData()['msg']);
  64. // }
  65. switch ($e->getMessage()) {
  66. case "Expired token":
  67. self::clear_session();
  68. $this->json_error('登入超时,请重新登录', null, self::ERR_CODE_LOGIN);
  69. break;
  70. case "Wrong number of segments":
  71. self::clear_session();
  72. $this->json_error('Token验证失败,请重新登录', null, self::ERR_CODE_LOGIN);
  73. break;
  74. default:
  75. $msg = "error:" . $e->getMessage();
  76. $this->json_error($msg);
  77. }
  78. }
  79. }
  80. /**
  81. * 获取登入token,并设置登入状态
  82. * @param $userId int 用户id
  83. * @param $loginTime int 用户登入时间
  84. * @param int $expire 设置jwt过期时间,从当前时间开始计算
  85. * @param null $exp 强制指定过期时间,用来刷新jwt
  86. * @return string
  87. */
  88. public static function createJwt($userId, $loginTime, $expire = 3600, $exp = null)
  89. {
  90. $nowtime = time();
  91. $exptime = $exp ? $exp : $nowtime + $expire;
  92. //添加 exptime,后端可以判断过期并退出, 不通过session
  93. $data = ['userId' => $userId, 'loginTime' => $loginTime, 'exptime' => $exptime];
  94. $token = [
  95. 'iss' => PRODUCT_URL, //签发者
  96. 'aud' => PRODUCT_URL, //jwt所面向的用户
  97. 'iat' => $nowtime, //签发时间
  98. 'nbf' => $nowtime + 10, //在什么时间之后该jwt才可用
  99. 'exp' => $exptime, //过期时间
  100. 'data' => $data //不要存放隐私信息,jwt可以保证内容不被修改,但可以被解码查看内容
  101. ];
  102. // 得到jwt
  103. $jwt_key = config('JWT_KEY');
  104. $jwt = JWT::encode($token, $jwt_key, 'HS256');
  105. //设置登入状态
  106. session(self::JWT_SESSION_NAME, $data);
  107. cookie(self::JWT_COOKIE_NAME, $jwt, 3600 * 12);
  108. return $jwt;
  109. }
  110. /**
  111. * 获取user对象
  112. * @return null|User
  113. */
  114. protected function getUser()
  115. {
  116. if (!$this->user) {
  117. $user = User::get($this->userId);
  118. if (!$user) {
  119. $this->json_error('找不到用户信息,请重新登入', null, self::ERR_CODE_LOGIN);
  120. }
  121. $this->user = $user;
  122. }
  123. return $this->user;
  124. }
  125. /**
  126. * 获取userid
  127. * @return null
  128. */
  129. protected function getUserId()
  130. {
  131. return $this->userId;
  132. }
  133. /**
  134. * 退出登入状态
  135. */
  136. public static function clear_session()
  137. {
  138. cookie(self::JWT_COOKIE_NAME, null);
  139. session(self::JWT_SESSION_NAME, null);
  140. }
  141. }