Laravel 13 API 认证详解

摘要

Laravel 提供了多种 API 认证方案。本文将深入讲解 Laravel 13 的 API 认证,包括:

  • Sanctum Token 认证
  • SPA 认证
  • 能力与权限
  • 认证最佳实践
  • 实战案例

本文适合希望掌握 API 认证的 Laravel 开发者。

1. Laravel Sanctum

1.1 安装

1
2
3
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

1.2 配置

1
2
3
4
5
6
7
8
9
10
// config/sanctum.php
return [
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', '')),
'guard' => ['web'],
'expiration' => null,
'middleware' => [
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
],
];

1.3 用户模型

1
2
3
4
5
6
use Laravel\Sanctum\HasApiTokens;

class User extends Model
{
use HasApiTokens;
}

2. Token 认证

2.1 创建 Token

1
2
3
4
5
6
7
8
9
10
11
12
use App\Models\User;

$user = User::find(1);

// 创建 Token
$token = $user->createToken('api-token');

// 返回纯文本 Token
return $token->plainTextToken;

// 创建带能力的 Token
$token = $user->createToken('api-token', ['read', 'write']);

2.2 使用 Token

1
2
curl -H "Authorization: Bearer {token}" \
https://example.com/api/user

2.3 保护路由

1
2
3
4
5
6
7
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

Route::middleware(['auth:sanctum'])->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
});

2.4 撤销 Token

1
2
3
4
5
// 撤销当前 Token
$request->user()->currentAccessToken()->delete();

// 撤销所有 Token
$request->user()->tokens()->delete();

3. Token 能力

3.1 定义能力

1
2
3
4
5
$token = $user->createToken('api-token', [
'read',
'write',
'delete',
]);

3.2 检查能力

1
2
3
if ($user->tokenCan('write')) {
// 允许写入
}

3.3 路由保护

1
2
3
Route::middleware(['auth:sanctum', 'abilities:read,write'])->group(function () {
// 需要 read 和 write 能力
});

4. SPA 认证

4.1 配置

1
2
// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1')),

4.2 CSRF 保护

1
2
3
4
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->statefulApi();
})

4.3 前端配置

1
2
3
4
5
6
7
8
// 获取 CSRF Token
axios.get('/sanctum/csrf-cookie').then(response => {
// 登录请求
axios.post('/login', {
email: 'user@example.com',
password: 'password'
});
});

5. 实战案例

5.1 登录接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);

$user = User::where('email', $request->email)->first();

if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}

$token = $user->createToken($request->device_name);

return response()->json([
'token' => $token->plainTextToken,
'user' => $user,
]);
}

public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();

return response()->json([
'message' => 'Logged out successfully',
]);
}

public function user(Request $request)
{
return $request->user();
}
}

5.2 注册接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
'device_name' => 'required',
]);

$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);

$token = $user->createToken($validated['device_name']);

return response()->json([
'token' => $token->plainTextToken,
'user' => $user,
], 201);
}

6. 最佳实践

6.1 Token 过期

1
2
// config/sanctum.php
'expiration' => 60 * 24, // 24 小时

6.2 Token 清理

1
2
// 定时清理过期 Token
$schedule->command('sanctum:prune-expired --hours=24')->daily();

6.3 安全建议

1
2
3
4
5
6
// 使用 HTTPS
// 限制 Token 能力
$token = $user->createToken('api-token', ['read']);

// 设置 Token 过期时间
'expiration' => 60 * 24,

7. 总结

Laravel Sanctum 提供了简单强大的 API 认证方案:

  1. Token 认证:适用于移动应用和 API
  2. SPA 认证:适用于单页应用
  3. 能力控制:细粒度权限管理
  4. 安全可靠:内置安全机制

参考资料