一、概述
中间件为过滤进入应用程序的 HTTP 请求提供了一种方便的机制。
例如,Laravel 内置了一个中间件来验证用户的身份认证。如果用户没有通过身份认证,中间件会将用户重定向到登录界面。但是,如果用户被认证,中间件将允许该请求进一步进入该应用。
Laravel 自带了一些中间件,包括身份验证、CSRF 保护等。所有这些中间件都位于 app/Http/Middleware 目录。
二、中间件的使用
1、创建中间件
php artisan make:middleware CheckToken
该命令会在 app/Http/Middleware/ 目录下生成一个名为 CheckToken.php 的文件。
2、编写中间件代码
<?php
namespace App\Http\Middleware;
use App\Constants\Auth\Constants;
use App\Services\Auth\AuthBaseService;
use Closure;
use Firebase\JWT\JWT;
use Illuminate\Encryption\Encrypter;
use \Illuminate\Http\Request;
use \Exception;
class CheckToken extends AuthBaseService
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// $uri = $request->route()->uri(); // 获取请求的路由名称 getAnalysis,之后进行rbac权限校验
$requestToken = $request->header('token');
if (empty($requestToken)) return $this->response(Constants::TOKEN_FAIL, '未登录');
try {
/**
* 解密请求token为jwt,如果解析不出,则抛出异常,由catch捕捉
* @var Encrypter
*/
$token = decrypt($requestToken, true);
// 校验jwt-token,如果jwt-token不合法,这里会抛出异常,由catch接手处理
$new = (array)JWT::decode($token, $this->getJwtSecret(), [$this->getAlg()]);
if (empty($new)) {
return $this->response(Constants::TOKEN_FAIL, 'token不合法');
}
// jwt-token二次校验
if (!isset($new['userId']) || !isset($new['iss']) || $new['iss'] !== 'seeLove') {
return $this->response(Constants::TOKEN_FAIL, 'token不合法');
}
$userId = $new['userId'];
$expireTtl = $this->ttl($this->tokenPrefix.$userId);
if ($expireTtl == -2 || !$expireTtl) return $this->response(Constants::TOKEN_FAIL,
'token已过期,请重新登录');
// 校验提交的token和缓存中的token是否一致(解决用户重新登录后,之前生成的token仍然有效[只允许一个用户持有一个token])
if ($requestToken !== $this->getCache($this->tokenPrefix.$userId)) {
return $this->response(Constants::TOKEN_FAIL, 'token已过期,请重新登录');
}
// 每次请求延长token45秒有效期
$this->setCache($this->tokenPrefix.$userId, $requestToken, $expireTtl + 45);
} catch (Exception $e) {
return $this->response(Constants::TOKEN_FAIL, 'token不合法');
}
return $next($request);
}
}
3、在app/Http/kernel.php引入该中间件
在 $routeMiddleware
数组中添加元素
// 校验用户token
'checkToken' => CheckToken::class,