在现代的web应用程序中,API是一个不可或缺的组成部分。同时,API的安全认证也是非常重要的。JWT(JSON Web Token)是一种基于Token认证的机制,被广泛应用于web应用中。在本文中,我们将使用ThinkPHP 5.1和JWT实现API安全认证。
首先,我们需要安装JWT包。通过Composer可以轻易地完成此项任务。
composer require firebase/php-jwt
接着,我们需要在应用中添加中间件,用于API认证。这里,我们将中间件定义于 application/middleware 目录下的ApiAuth.php 文件中:
namespace app\middleware; use think\facade\Request; use Firebase\JWT\JWT; use app\exception\ApiException; class ApiAuth { public function handle($request, \Closure $next) { $header = Request::header(); if (!isset($header['authorization'])) { throw new ApiException('Token not found', 401); } $token = explode(' ', $header['authorization']); if (count($token) !== 2) { throw new ApiException('Token format error', 401); } $payload = JWT::decode($token[1], env('JWT_SECRET'), ['HS256']); if (!$payload || !isset($payload->uid)) { throw new ApiException('Token invalid', 401); } return $next($request); } }
通过上述代码,我们定义了一个中间件 ApiAuth,用于检查请求中的 Token 是否有效。中间件的入口是 handle 方法,首先对 Token 进行检查,如果没有 Token,则返回状态码 401(Unauthorized);如果格式不对,则同样返回 401;最后,通过 JWT 解密 Token 中的数据,并检查其中是否包含uid,如果有,则说明 Token 有效。若 Token 失效,则同样返回状态码 401。
以上就是中间件的定义。接着,我们可以在应用中添加自定义的路由。
use think\facade\Route; Route::group('api', function() { Route::group('v1', function() { Route::get('hello', 'api/v1.Test/index')->middleware('ApiAuth'); }); });
以上代码定义了一个路由,其目录为 api/v1,访问路径为 /api/v1/hello 。并且该路由使用中间件 ApiAuth 进行检查认证。
最后,我们来看一下 JWT Token 的创建与解析。JWT 的创建需要以下三个参数:iss(Issuer)- 签名的颁发者,aud(Audience)- 接收者,exp(Expiration Time)- 过期时间。第三个参数则是使用 env() 函数获取我们在 .env 文件中定义的加密密钥。
use Firebase\JWT\JWT; $key = env('JWT_SECRET'); $token = [ "iss" => env('APP_NAME'), "aud" => $_SERVER['HTTP_HOST'], "exp" => time() + 3600, "uid" => $uid ]; $jwt = JWT::encode($token, $key);
以上代码实现了 JWT Token 的创建,并返回创建好的 Token 供用户进行使用。其中 $uid 是代表用户标识的变量。
最后,我们再回到ApiAuth.php文件中,看一下 Token 的解析部分。上文中,我们看到了使用JWT::decode()函数解析 Token:
$payload = JWT::decode($token[1], env('JWT_SECRET'), ['HS256']);
比较重要的是第三个参数,它指定了签名算法。这里,我们使用的是 HS256,即 HMAC-SHA256,也是 JWT 所推荐的算法之一。
通过上面的代码,我们很容易地实现了基于JWT的API认证功能。