Thinkphp6集成JWT API接口引入token
发表于:2022-03-06 14:20:15浏览:252次
JWT 全称 Json Web token,是为了在网络应用环境间传递声明而执行的一种基于json的开放标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息,以便于从服务器获取资源,也可以增加一些额外的其他业务逻辑所必须的声明信息,该token也可之间被用于认证,也可以被加密。
PHP有很多JWT包,这里主要介绍使用lcobucci/jwt包。
安装:
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.gougucms.com';
// claim aud签发作者
private $aud = 'gougucms';
// claim uid
private $uid;
// secrect
private $secrect = 'GOUGUCMS';
// 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
/**
* +----------------------------------------------------------------------
* | Api中间件
* +----------------------------------------------------------------------
*/
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([], 110, 'token格式错误');
}
$jwtAuth = JwtAuth::getInstance();
$jwtAuth->setToken($token);
if ($jwtAuth->validate() && $jwtAuth->verify()) {
return $next($request);
} else {
$this->result([], 111, 'token已过期');
}
} else {
$this->result([], 112, '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);
}
}
调用:
文件:\app\api\controller\Index.php
<?php
/**
* +----------------------------------------------------------------------
* | api控制器
* +----------------------------------------------------------------------
*/
namespace app\api\controller;
use app\api\service\JwtAuth;
use think\facade\Db;
use think\facade\Request;
class Index extends Base
{
/**
* 控制器中间件 [登录、注册 不需要鉴权]
* @var array
*/
protected $middleware = [
'app\api\middleware\Api' => ['except' => ['login', 'register']],
];
/**
* @api {post} /User/login 01、会员登录
* @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 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, '用户已被禁用');
}
}
}
}
推荐文章
- 深入解析 Python 中的 JSON 处理工具
- python pip安装库—下载源更换(清华源、阿里源、中科大源、豆瓣源)
- php接口优化 使用curl_multi_init批量请求
- Vue又出新品——petite-vue
- PHP函数探究——array_key_first()
- 2024 年开发人员必须了解的 6 大 PHP 框架?
- 深化 PHP 的能力边界:解锁并优雅利用外部函数接口(FFI)
- python提示No module named setuptools,wget提示ERROR 403: SSL is required及报错Cannot fetch index base URL
- Thinkphp6集成JWT API接口引入token
- js保留两位小数的合理处理方法