安装:
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();
}
}
|