| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | <?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 = system_salt();            $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));            $arr = (array)$decoded;            if (!isset($arr['exp']) || $arr['exp'] < time()) {                self::clear_session();                throw new \think\Exception('登入超时,请重新登录');            } else {                //鉴权成功                $this->userId = $arr['data']->userId;                $loginTime = $arr['data']->loginTime;                $exptime = $arr['exp'];                //限制账号多次登入//                if ($this->getUser()->getData('login_time') > $loginTime) {//                    $this->clear_session();//                    throw new \think\Exception('您的账号已经在其它地方登入');//                }                // 每次刷新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 = system_salt();        $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);    }}
 |