使用JWT身份验证构建安全的Laravel API
在使用Laravel构建API时,确保安全的身份验证至关重要,特别是在处理用户数据时。JSON Web Tokens (JWT) 提供了一种强大的方法来处理无状态应用程序中的身份验证,允许在各方之间安全地传输用户信息。本指南将引导您通过使用JWT身份验证构建安全的Laravel API的过程。
前提条件
- 基本的PHP和Laravel知识。
- 在您的机器上安装Laravel(最好是Laravel 9或更新版本)。
- 安装Composer。
- 为您的应用程序设置MySQL或其他数据库。
步骤1:创建新的Laravel项目
首先,使用Composer创建一个新的Laravel项目:
composer create-project laravel/laravel laravel-jwt-api
导航到您的项目目录:
cd laravel-jwt-api
步骤2:安装JWT身份验证包
在Laravel中最常用的JWT身份验证包是tymon/jwt-auth。使用Composer安装它:
composer require tymon/jwt-auth
安装包后,发布JWT配置:
php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"
这将在您的项目中创建一个config/jwt.php文件。
步骤3:生成JWT密钥
生成一个JWT将用于签名令牌的密钥:
php artisan jwt:secret
这将向您的.env文件添加一个JWT_SECRET条目,用于编码和解码令牌。
步骤4:设置身份验证
要设置JWT身份验证,您需要为您的API配置默认守卫。按如下方式更新config/auth.php文件:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],步骤5:创建用户模型和迁移
如果您还没有创建User模型,可以与其迁移文件一起创建:
php artisan make:model User -m
打开database/migrations/中生成的迁移文件,并添加必要的字段,如name、email和password:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
运行迁移以创建users表:
php artisan migrate
步骤6:在用户模型中实现JWT方法
在User模型(app/Models/User.php)中,实现JWTSubject接口和所需的方法:
use TymonJWTAuthContractsJWTSubject;
use IlluminateFoundationAuthUser as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
public function getJWTIdentifier()
{
return $this->getKey(); // Usually the primary key (id)
}
public function getJWTCustomClaims()
{
return [];
}
}步骤7:创建身份验证控制器
创建一个控制器来处理用户身份验证:
php artisan make:controller AuthController
在AuthController.php中,添加用于注册用户、登录和注销的方法:
<?php
namespace AppHttpControllers;
use AppModelsUser;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use IlluminateSupportFacadesHash;
use TymonJWTAuthFacadesJWTAuth;
class AuthController extends Controller
{
// User Registration
public function register(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = JWTAuth::fromUser($user);
return response()->json(['token' => $token], 201);
}
// User Login
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (!$token = Auth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json(['token' => $token]);
}
// Logout User (Invalidate Token)
public function logout()
{
Auth::logout();
return response()->json(['message' => 'Successfully logged out']);
}
// Get Authenticated User
public function me()
{
return response()->json(Auth::user());
}
}步骤8:定义API路由
在routes/api.php中添加身份验证路由:
use AppHttpControllersAuthController;
use IlluminateSupportFacadesRoute;
Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
// Protected routes (require JWT token)
Route::middleware('auth:api')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::get('me', [AuthController::class, 'me']);
});这些路由处理用户注册、登录、注销和获取已认证用户。
步骤9:保护API路由
要保护其他API路由,您可以使用auth:api中间件。例如,如果您有一个posts的资源路由:
Route::middleware('auth:api')->group(function () {
Route::resource('posts', PostController::class);
});
这确保只有经过身份验证的用户可以访问这些路由。
步骤10:测试API
您可以使用Postman或cURL等工具测试您的API。
- 注册用户:
POST /api/register
Host: your-domain.com
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"password": "password",
"password_confirmation": "password"
} - 登录:
POST /api/login
Host: your-domain.com
Content-Type: application/json
{
"email": "john@example.com",
"password": "password"
}这将返回一个令牌,您可以用它来验证其他请求。 - 访问受保护的路由:要访问像GET /api/me这样的受保护路由,请在Authorization头中包含令牌:
Authorization: Bearer <token>
步骤11:刷新JWT令牌(可选)
要刷新令牌,您可以在AuthController中添加一个方法:
public function refresh()
{
$token = Auth::refresh();
return response()->json(['token' => $token]);
}添加刷新路由:
Route::post('refresh', [AuthController::class, 'refresh'])->middleware('auth:api');
结论
通过遵循本指南,您已经构建了一个安全的Laravel API,使用JWT身份验证,实现了用户注册、登录和访问受保护的路由。JWT允许您维护无状态的身份验证机制,这对于扩展API尤其有用。通过此设置,您可以进一步自定义应用程序的身份验证逻辑,并集成其他功能,例如基于角色的访问控制和用于长期会话的刷新令牌。
