站长资讯网
最全最丰富的资讯网站

thinkPHP配置jwt(代码实例)

thinkPHP配置jwt(代码实例)

thinkphp5.1-jwt的安装与使用

安装jwt插件

在composer.json的require中加入如下配置

"firebase/php-jwt": "^5.0"

在项目根目录下执行composer update即可.

创建一个auth中间件

php think make:middleware Auth

打开applicationhttpmiddlewareAuth文件

<?php namespace apphttpmiddleware; use FirebaseJWTJWT; use FirebaseJWTSignatureInvalidException; use thinkexceptionTokenException; use thinkexceptionValidateException; use think acadeCache; use think acadeConfig;  class Auth {  public function handle($request, Closure $next)  {  $bearer_token = [];  $bearer = $request->header('authorization');//取header中的token  if ($bearer !== null) {  //不空尝试去匹配  preg_match('/bearers*(S+)/i', $bearer, $bearer_token);  }  if (empty($bearer_token[1])) {  //匹配不到结果尝试去url中获取  if ($request->param('token') !== null) {  $token = $request->param('token');  }else{  throw new TokenException('请登录', 401);  }  }else{  $token=$bearer_token[1];  }  try {  $de_token = JWT::decode($token, Config::get('JWT_KEY'), Config::get('JWT_ENCRYPTION'));  } catch (SignatureInvalidException $exception) {  //捕获JWT解析错误  throw new TokenException('无效令牌', 401);  } catch (Exception $exception) {  throw new TokenException('请重新登录', 401);  }  if ($de_token->voe < time() && $de_token->exp > time()) {  throw new TokenException('请换取新令牌', 402);  } else if ($de_token->voe < time()) {  throw new TokenException('请重新登录', 401);  }  if (Cache::tag('login')->get('token_' . $de_token->data->uid) != $token) {  throw new TokenException('用户信息错误,请重新登录', 401);  }  if ($de_token->data->is_ban == 1) {  throw new ValidateException('该账户已被封禁');  }  $request->auth = $de_token->data->uid;  return $next($request);  } }

创建一个控制器Login
php think make:controller login/Login --plain
代码如下

<?php namespace applogincontroller; use appcommonhelp; use appcommonserviceOperationToken; use thinkController; use thinkDb; use thinkRequest; class Login extends Controller {  public function login(Request $request)  {  $info = Db::name('user')->field('id,uuid,nick,gender,icon,im_accid,im_icon,is_ban')->where('del_time', '=', '0')->where(['mobile' => $request->param('phone'), 'password' => md5($request->param('password'))])->findOrEmpty();  if ($info == null || empty($info)) {  return help::errJsonReturn('账号或密码错误');  }  $token = OperationToken::crearToken($info['id'], $info['uuid'], $info['is_ban']);  return json([  'type' => 'Bearer ',  'access_token'=>$token['token'],  'exp_time'=>$token['exp'],  'voe_time'=>$token['voe'],  'iat_time'=>time()  ]);  } }

在application下新建common文件夹,在common下新建service文件夹,service文件夹下创建

OperationToken.php

<?php namespace appcommonservice; use thinkDb; use think acadeCache; use FirebaseJWTJWT; use think acadeConfig; class OperationToken {  public static function crearToken(int $uid, string $uuid, int $is_ban): array  {  $time = time();  $info_token = [  'iat' => $time,//签发时间  'voe' => Config::get('TOKEN_VOE',7200) + $time,//换取有效时间  'exp' => Config::get('TOKEN_EXP',3600)+$time,//有效时间  'sign' => base64_encode($uuid),//签名  'data' => [  'uid' => $uid,//用户id  'is_ban' => $is_ban,//是否被禁用  ]  ];  $token = JWT::encode($info_token, Config::get('JWT_KEY'));  Cache::tag('login')->set('token_' . $uid, $token, Config::get('TOKEN_VOE',7200) + $time);  Db::name('user_login_log')->insert(  [  'uid'=>$uid,  'token'=>$token,  'iat_time'=>$time,  'ip'=>ip2long(request()->ip()),  'exp_time'=>Config::get('TOKEN_EXP',3600)+$time,  'voe_time'=> Config::get('TOKEN_VOE',7200) + $time  ]  );  return [  'token'=>$token,   'voe' =>Config::get('TOKEN_VOE',7200) + $time,  'exp' => Config::get('TOKEN_EXP',3600)+$time];  } }

config/app.php文档末尾追加参数并接管错误控制

// 异常处理handle类 留空使用 thinkexceptionHandle 'exception_handle' => function ($e) {  //参数验证错误  if ($e instanceof thinkexceptionValidateException) {  return json(['msg' => $e->getError()], 422);  }  //route未定义  if ($e instanceof thinkexceptionValidateException) {  return json(['msg' => $e->getMessage()], 404);  } //token过期/无效 401-令牌/账号密码错误 402-令牌过期可旧换新 403-无权限访问  if ($e instanceof hinkexceptionTokenException) {  return json(['msg' => $e->getError()], $e->getCode());  } // 请求异常  if ($e instanceof HttpException && request()->isAjax()) {  return response(['msg' => $e->getMessage()], $e->getStatusCode());  }  },

thinkphp5.1-jwt的安装与使用与路由参数验证

在thinkphplibrary hinkexception下新建TokenException.php

代码如下

<?php namespace thinkexception; class TokenException extends HttpException {  protected $error;  public function __construct($error, $code = 0)  {  $this->error = $error;  $this->message = $error;  $this->code = $code;  }  /**  * 获取验证错误信息  * @access public  * @return array|string  */  public function getError()  {  return $this->error;  } }

创建一个login的验证器

php think make:validate login/Login

代码如下

<?php namespace applogin validate;use thinkValidate;class Login extends Validate { /**  * 定义验证规则  * 格式:'字段名' => ['规则1','规则2'...]  *  * @var array */  protected $rule = [ 'phone'=>'require|mobile',  'password'=>'require|length:4,12'  ];   /**  * 定义错误信息  * 格式:'字段名.规则名' => '错误信息'  *  * @var array */  protected $message = [ 'phone.mobile'=>'phone格式错误',  'password.length'=>'密码长度错误'  ]; protected $scene=[ 'login'=>['phone','password']  ]; }

打开route/route.php

代码如下

<?php use think acadeRoute; Route::get('/','index/Index/index'); Route::group('account',function (){  Route::post('/login','login/Login/login')->validate('applogin alidateLogin','login'); }); //需要验证登录 Route::group('api',function (){  Route::post('/user','index/Index/index'); })->middleware(apphttpmiddlewareAuth::class);

这里的middleware按照官方文档是可以注册到middleware.php中,但在测试中发现问题.路由不执行middleware方法在访问时会由上至下顺序执行middleware.php中注册的所有中间件,因此改写为middleware(apphttpmiddlewareAuth::class);去使用中间件在common下新建一个help.php

代码如下

<?php namespace appcommon; class help {  public static function susJsonReturn(array $data=[],string $msg='请求成功',int $code=1)  {  return json([  'msg'=>$msg,  'data'=>$data,  'code'=>$code  ]);  }  public static function errJsonReturn(string $msg = '请求失败', int $code = 0, array $data = [])  {  return json([  'msg'=>$msg,  'data'=>$data,  'code'=>$code  ]);  } }

到数据库中新建一个数据库,新建两张表

CREATE TABLE `xn_user` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `uuid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'uuid',  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '登录密码',  `name` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '真实姓名',  `nick` varchar(8) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '昵称',  `gender` enum('1','2','0') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '用户性别,0 表示未知,1 表示男,2 女表示女',  `regist_time` int(11) unsigned DEFAULT NULL,  `icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '头像',  `mobile` char(11) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '手机号',  `im_accid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'im账号',  `im_icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'im头像',  `im_email` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'im邮箱',  `im_birth` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'im生日',  `im_mobile` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'im手机号码',  `create_time` int(11) unsigned DEFAULT '0',  `del_time` int(11) unsigned DEFAULT '0',  `is_ban` enum('0','1') COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT '是否封号',  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `xn_user_login_log` (  `uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户id',  `token` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '登录时的令牌',  `iat_time` int(11) DEFAULT '0' COMMENT '登录时间',  `ip` bigint(20) unsigned DEFAULT '0' COMMENT '登录ip-ip2long',  `exp_time` int(11) DEFAULT '0' COMMENT '失效时间',  `voe_time` int(11) DEFAULT '0' COMMENT 'token旧换新有效时间',  KEY `login_log_uid` (`uid`,`ip`,`token`(32)) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

推荐教程:《TP5》

赞(0)
分享到: 更多 (0)