123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- <?php
- /**
- * Created by PhpStorm.
- * User: 中闽 < 1464674022@qq.com >
- * Date: 2019/12/5
- * Time: 17:44
- */
- namespace app\api\controller\base;
- use app\common\model\User;
- use Exception;
- use Firebase\JWT\JWT;
- use Firebase\JWT\Key;
- use think\exception\HttpResponseException;
- /**
- * 登入鉴权的接口父类
- * Class Permissions
- * @package app\api\controller\base
- */
- class Permissions extends Base
- {
- const JWT_COOKIE_NAME = 'x-token';
- const JWT_SESSION_NAME = 'user_info';
- private $userId;
- private $user;
- protected function _initialize()
- {
- parent::_initialize();
- //get token from header param body
- $jwt = $this->request->header('x-token', "");
- if (!$jwt) {
- $jwt = $this->request->param('x-token', "");
- if (!$jwt) {
- $callbackBody = file_get_contents('php://input');
- if (!$callbackBody) {
- $this->json_error('请先登入', null, self::ERR_CODE_LOGIN);
- }
- $callbackJson = json_decode($callbackBody, true);
- $jwt = isset($callbackJson['x-token']) ? $callbackJson['x-token'] : '';
- if (!$jwt) {
- $this->json_error('请先登入', null, self::ERR_CODE_LOGIN);
- }
- }
- }
- //check x-token
- try {
- JWT::$leeway = 60;
- $jwt_key = config('JWT_KEY');
- $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));
- $arr = (array)$decoded;
- if (!isset($arr['exp']) || $arr['exp'] < time()) {
- throw new \think\Exception('Expired token');
- } else {
- //鉴权成功
- $this->userId = $arr['data']->userId;
- $loginTime = $arr['data']->loginTime;
- $exptime = $arr['exp'];
- // 每次刷新jwt,loginTime要保持不变
- self::createJwt($this->userId, $loginTime, 3600, $exptime);
- return;
- }
- } catch (Exception $e) {
- // if ($e instanceof HttpResponseException) {
- // $this->json_error($e->getResponse()->getData()['msg']);
- // }
- switch ($e->getMessage()) {
- case "Expired token":
- self::clear_session();
- $this->json_error('登入超时,请重新登录', null, self::ERR_CODE_LOGIN);
- break;
- case "Wrong number of segments":
- self::clear_session();
- $this->json_error('Token验证失败,请重新登录', null, self::ERR_CODE_LOGIN);
- break;
- default:
- $msg = "error:" . $e->getMessage();
- $this->json_error($msg);
- }
- }
- }
- /**
- * 获取登入token,并设置登入状态
- * @param $userId int 用户id
- * @param $loginTime int 用户登入时间
- * @param int $expire 设置jwt过期时间,从当前时间开始计算
- * @param null $exp 强制指定过期时间,用来刷新jwt
- * @return string
- */
- public static function createJwt($userId, $loginTime, $expire = 3600, $exp = null)
- {
- $nowtime = time();
- $exptime = $exp ? $exp : $nowtime + $expire;
- //添加 exptime,后端可以判断过期并退出, 不通过session
- $data = ['userId' => $userId, 'loginTime' => $loginTime, 'exptime' => $exptime];
- $token = [
- 'iss' => PRODUCT_URL, //签发者
- 'aud' => PRODUCT_URL, //jwt所面向的用户
- 'iat' => $nowtime, //签发时间
- 'nbf' => $nowtime + 10, //在什么时间之后该jwt才可用
- 'exp' => $exptime, //过期时间
- 'data' => $data //不要存放隐私信息,jwt可以保证内容不被修改,但可以被解码查看内容
- ];
- // 得到jwt
- $jwt_key = config('JWT_KEY');
- $jwt = JWT::encode($token, $jwt_key, 'HS256');
- //设置登入状态
- session(self::JWT_SESSION_NAME, $data);
- cookie(self::JWT_COOKIE_NAME, $jwt, 3600 * 12);
- return $jwt;
- }
- /**
- * 获取user对象
- * @return null|User
- */
- protected function getUser()
- {
- if (!$this->user) {
- $user = User::get($this->userId);
- if (!$user) {
- $this->json_error('找不到用户信息,请重新登入', null, self::ERR_CODE_LOGIN);
- }
- $this->user = $user;
- }
- return $this->user;
- }
- /**
- * 获取userid
- * @return null
- */
- protected function getUserId()
- {
- return $this->userId;
- }
- /**
- * 退出登入状态
- */
- public static function clear_session()
- {
- cookie(self::JWT_COOKIE_NAME, null);
- session(self::JWT_SESSION_NAME, null);
- }
- }
|