| 
 
 安装:  
composer require lcobucci/jwt  
 
封装:app\api\service 下新建JwtAuth.php  
<?php
namespace app\api\service;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;
/**
 * 单例 一次请求中所有出现jwt的地方都是一个用户
 * Class JwtAuth
 * @package app\api\service
 */
class JwtAuth
{
    // jwt token
    private $token;
    // jwt 过期时间
    private $expTime = 3600;
    // claim iss
    private $iss = 'api.ahybb.com';
    // claim aud
    private $aud = 'ahybb';
    // claim uid
    private $uid;
    // secrect
    private $secrect = '1faASDF3';
    // decode token
    private $decodeToken;
    // 单例模式JwtAuth句柄
    private static $instance;
    // 获取JwtAuth的句柄
    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    // 私有化构造函数
    private function __construct()
    {
    }
    // 私有化clone函数
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
    // 获取token
    public function getToken()
    {
        return (string)$this->token;
    }
    // 设置token
    public function setToken($token)
    {
        $this->token = $token;
        return $this;
    }
    // 设置uid
    public function setUid($uid)
    {
        $this->uid = $uid;
        return $this;
    }
    // 获取uid
    public function getUid()
    {
        return $this->uid;
    }
    // 编码jwt token
    public function encode()
    {
        $time = time();
        $this->token = (new Builder())->setHeader('alg', 'HS256')
            ->setIssuer($this->iss)
            ->setAudience($this->aud)
            ->setIssuedAt($time)
            ->setExpiration($time + $this->expTime)
            ->set('uid', $this->uid)
            ->sign(new Sha256(), $this->secrect)
            ->getToken();
        return $this;
    }
    public function decode()
    {
        if (!$this->decodeToken) {
            $this->decodeToken = (new Parser())->parse((string)$this->token); // Parses from a string
            $this->uid = $this->decodeToken->getClaim('uid');
        }
        return $this->decodeToken;
    }
    // validate
    public function validate()
    {
        $data = new ValidationData(); // It will use the current time to validate (iat, nbf and exp)
        $data->setIssuer($this->iss);
        $data->setAudience($this->aud);
        $data->setId($this->uid);
        return $this->decode()->validate($data);
    }
    // verify token
    public function verify()
    {
        $signer = new Sha256();
        return $this->decode()->verify($signer, $this->secrect);
    }
}
  
中间件:app\api\middleware 下新建api.php  
<?php
namespace app\api\middleware;
use app\api\service\JwtAuth;
use think\facade\Request;
use think\Response;
use think\exception\HttpResponseException;
class Api
{
    public function handle($request, \Closure $next)
    {
        $token = Request::header('token');
        if ($token) {
            if (count(explode('.', $token)) <> 3) {
                $this->result([], 0, 'token格式错误');
            }
            $jwtAuth = JwtAuth::getInstance();
            $jwtAuth->setToken($token);
            if ($jwtAuth->validate() && $jwtAuth->verify()) {
                return $next($request);
            } else {
                $this->result([], 0, 'token已过期');
            }
        } else {
            $this->result([], 0, 'token不能为空');
        }
        return $next($request);
    }
    /**
     * 返回封装后的API数据到客户端
     * @param  mixed   $data 要返回的数据
     * @param  integer $code 返回的code
     * @param  mixed   $msg 提示信息
     * @param  string  $type 返回数据格式
     * @param  array   $header 发送的Header信息
     * @return Response
     */
    protected function result($data, int $code = 0, $msg = '', string $type = '', array $header = []): Response
    {
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'time' => time(),
            'data' => $data,
        ];
        $type     = $type ?: 'json';
        $response = Response::create($result, $type)->header($header);
        throw new HttpResponseException($response);
    }
}
  
中间件别名:根目录下/config/middleware.php  
<?php
// 中间件配置
return [
    // 别名或分组
    'alias'    => [
    	'tokencheck'=> app\api\middleware\Api::class
    ],
    // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
    'priority' => [],
];
  
api接口使用?  
namespace app\api\controller;
use app\api\service\JwtAuth;
use app\common\model\Users;
use think\facade\Db;
use think\facade\Request;
class User extends Base
{
    /**
     * 注册控制器中间件 [登录、注册 不需要鉴权]
       另外全局中间件和应用中间件
     * @var array
     */
    protected $middleware = [
        'tokencheck' => ['except' => ['login', 'register','test']],
    ];
    /**
     * @api {post} /User/login 01、会员登录
     * @apiGroup User
     * @apiVersion 6.0.0
     * @apiDescription 系统登录接口,返回 token 用于操作需验证身份的接口
     * @apiParam (请求参数:) {string}     		username 登录用户名
     * @apiParam (请求参数:) {string}     		password 登录密码
     * @apiParam (响应字段:) {string}     		token    Token
     * @apiSuccessExample {json} 成功示例
     * {"code":1,"msg":"登录成功","time":1563525780,"data":{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuc2l5dWNtcy5jb20iLCJhdWQiOiJzaXl1Y21zX2FwcCIsImlhdCI6MTU2MzUyNTc4MCwiZXhwIjoxNTYzNTI5MzgwLCJ1aWQiOjEzfQ.prQbqT00DEUbvsA5M14HpNoUqm31aj2JEaWD7ilqXjw"}}
     * @apiErrorExample {json} 失败示例
     * {"code":0,"msg":"帐号或密码错误","time":1563525638,"data":[]}
     */
    
        public function test()
    {
        $this->result(['token' => 11111], 1, '测试','',['bcx'=>212122222]);
          
    }
    public function login(string $username, string $password)
    {
        // 校验用户名密码
        $user = Users::where('email|mobile', $username)
            ->where('password', md5($password))
            ->find();
        if (empty($user)) {
            $this->result([], 0, '帐号或密码错误');
        } else {
            if ($user['status'] == 1) {
                //获取jwt的句柄
                $jwtAuth = JwtAuth::getInstance();
                $token = $jwtAuth->setUid($user['id'])->encode()->getToken();
                //更新信息
                Users::where('id', $user['id'])
                    ->update(['last_login_time' => time(), 'last_login_ip' => Request::ip()]);
                $this->result(['token' => $token], 1, '登录成功');
            } else {
                $this->result([], 0, '用户已被禁用');
            }
        }
    }
    /**
     * @api {post} /User/register 02、会员注册
     * @apiGroup User
     * @apiVersion 6.0.0
     * @apiDescription  系统注册接口,返回是否成功的提示,需再次登录
     * @apiParam (请求参数:) {string}     		email 邮箱
     * @apiParam (请求参数:) {string}     		password 密码
     * @apiSuccessExample {json} 成功示例
     * {"code":1,"msg":"注册成功","time":1563526721,"data":[]}
     * @apiErrorExample {json} 失败示例
     * {"code":0,"msg":"邮箱已被注册","time":1563526693,"data":[]}
     */
    public function register(string $email, string $password){
        // 密码长度不能低于6位
        if (strlen($password) < 6) {
            $this->result([], 0, '密码长度不能低于6位');
        }
        // 邮箱合法性判断
        if (!is_email($email)) {
            $this->result([], 0, '邮箱格式错误');
        }
        // 防止重复
        $id = Db::name('users')->where('email|mobile', '=', $email)->find();
        if ($id) {
            $this->result([], 0, '邮箱已被注册');
        }
        // 注册入库
        $data = [];
        $data['email']           = $email;
        $data['password']        = md5($password);
        $data['last_login_time'] = $data['create_time'] = time();
        $data['create_ip']       = $data['last_login_ip'] = Request::ip();
        $data['status']          = 1;
        $data['type_id']         = 1;
        $data['sex']             = Request::post('sex') ? Request::post('sex') : 0;
        $id = Db::name('users')->insertGetId($data);
        if ($id) {
            $this->result([], 1, '注册成功');
        } else {
            $this->result([], 0, '注册失败');
        }
    }
    /**
     * @api {post} /User/index 03、会员中心首页
     * @apiGroup User
     * @apiVersion 6.0.0
     * @apiDescription  会员中心首页,返回用户个人信息
     * @apiParam (请求参数:) {string}     		token Token
     * @apiSuccessExample {json} 响应数据样例
     * {"code":1,"msg":"","time":1563517637,"data":{"id":13,"email":"test110@qq.com","password":"e10adc3949ba59abbe56e057f20f883e","sex":1,"last_login_time":1563517503,"last_login_ip":"127.0.0.1","qq":"123455","mobile":"","mobile_validated":0,"email_validated":0,"type_id":1,"status":1,"create_ip":"127.0.0.1","update_time":1563507130,"create_time":1563503991,"type_name":"注册会员"}}
     */
    public function index()
    {
        $user = Db::name('users')
            ->alias('u')
            ->leftJoin('users_type ut', 'u.type_id = ut.id')
            ->field('u.*,ut.name as type_name')
            ->where('u.id', $this->getUid())
            ->find();
        return $this->result($user, 1, '');
    }
    /**
     * @api {post} /User/editPwd 04、修改密码
     * @apiGroup User
     * @apiVersion 6.0.0
     * @apiDescription  修改会员密码,返回成功或失败提示
     * @apiParam (请求参数:) {string}     		token Token
     * @apiParam (请求参数:) {string}     		oldPassword 原密码
     * @apiParam (请求参数:) {string}     		newPassword 新密码
     * @apiSuccessExample {json} 成功示例
     * {"code":1,"msg":"密码修改成功","time":1563527107,"data":[]}
     * @apiErrorExample {json} 失败示例
     * {"code":0,"msg":"token已过期","time":1563527082,"data":[]}
     */
    public function editPwd(string $oldPassword, string $newPassword){
        // 密码长度不能低于6位
        if (strlen($newPassword) < 6) {
            $this->result([], 0, '密码长度不能低于6位');
        }
        // 查看原密码是否正确
        $user = Users::where('id', $this->getUid())
            ->where('password', md5($oldPassword))
            ->find();
        if (!$user) {
            $this->result([], 0, '原密码输入有误');
        }
        //更新信息
        $user = Users::find($this->getUid());
        $user->password = md5($newPassword);
        $user->save();
        $this->result([], 1, '密码修改成功');
    }
    /**
     * @api {post} /User/editInfo 05、修改信息
     * @apiGroup User
     * @apiVersion 6.0.0
     * @apiDescription  修改用户信息,返回成功或失败提示
     * @apiParam (请求参数:) {string}     		token Token
     * @apiParam (请求参数:) {string}     		sex 性别 [1男/0女]
     * @apiParam (请求参数:) {string}     		qq  qq
     * @apiParam (请求参数:) {string}     		mobile  手机号
     * @apiSuccessExample {json} 成功示例
     * {"code":0,"msg":"修改成功","time":1563507660,"data":[]}
     * @apiErrorExample {json} 失败示例
     * {"code":0,"msg":"token已过期","time":1563527082,"data":[]}
     */
    public function editInfo(){
        $data['sex']    = trim(Request::param("sex"));
        $data['qq']     = trim(Request::param("qq"));
        $data['mobile'] = trim(Request::param("mobile"));
        if ($data['mobile']) {
            // 不可和其他用户的一致
            $id = Users::
                where('mobile', $data['mobile'])
                ->where('id', '<>', $this->getUid())
                ->find();
            if ($id) {
                $this->result([], 0, '手机号已存在');
            }
        }
        // 更新信息
        Users::where('id', $this->getUid())
            ->update($data);
        $this->result([], 0, '修改成功');
    }
    /**
     * 获取用户id
     * @return mixed
     */
    protected function getUid(){
        $jwtAuth = JwtAuth::getInstance();
        return $jwtAuth->getUid();
    }
}
  
                
        
    
 
 |