ThinkPHP 5.1:使用JWT做API认证

2023-06-17 08:46:46

在现代的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认证功能。

  • 作者:
  • 原文链接:
    更新时间:2023-06-17 08:46:46