做Laravel API开发时,选什么认证方式大概率会纠结Sanctum还是Passport——毕竟这俩都是官方出的,功能看起来都能搞定身份验证,但实际用起来踩的坑、适合的场景差得特别多。很多新手刚上手就瞎选,结果要么不够安全,要么后续扩展麻烦,今天就把这俩讲透,从本质到场景再到坑点,全给你捋明白。
一、为什么Sanctum和Passport会让开发者纠结
这俩都是Laravel官方为API认证出的工具,但定位完全不同:Sanctum是“轻量选手”,主打简单的无状态Token认证,专门给自己开发的前端(比如SPA、移动端APP)用;Passport是“专业选手”,严格遵循OAuth2.0标准,专门给对外的第三方应用提供授权认证。很多人分不清定位,就凭着“官方推的”“用的人多”瞎选,结果要么开发时卡壳,要么后续扩展不了。
二、Sanctum:无状态Token的入门级选择
2.1 Sanctum到底是什么
打个比方:你开了个便利店,给常来的老客户设了临时门禁卡,客户每次进门不用带身份证,刷门禁卡就行——便利店不用记你任何信息,只要能扫门禁卡的二维码就放行。Sanctum就是干这个的:它给你生成一个无状态的Token,你每次请求API时带上它,服务器只查这个Token的合法性,不用存你的会话信息,开发起来特别快。
示例:Sanctum实现简单API认证(技术栈:Laravel 9 + Sanctum)
// 1. 先安装Sanctum:composer require laravel/sanctum
// 2. 发布配置:php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
// 3. 迁移生成表:php artisan migrate
// routes/api.php:API路由配置
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
// 登录接口:用户提交账号密码,获取Token
Route::post('/login', [AuthController::class, 'login']);
// 需要认证的接口:必须带Sanctum Token才能访问
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
// 直接返回当前登录用户信息,Sanctum自动验证Token合法性
return $request->user();
});
// AuthController.php:登录逻辑
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class AuthController extends Controller
{
// 登录方法:验证账号密码,返回Token
public function login(Request $request)
{
// 验证请求参数,只允许传email和password
$request->validate([
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
// 尝试登录,用Laravel自带的Auth验证
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json(['message' => '账号或密码错误'], 401);
}
// 登录成功:创建对应设备的Token,方便后续清理
$user = Auth::user();
return response()->json([
'token' => $user->createToken($request->device_name ?? 'web')->plainTextToken,
'user' => $user
], 200);
}
}
2.2 Sanctum的适用场景
适合仅给自己的前端(内部系统)用的API:比如你做了个后台管理系统,前端用Vue,API是Laravel,只要前后端自己用,不用给第三方开放,Sanctum足够:开发快,没有复杂配置,Token逻辑简单,性能也高。
2.3 Sanctum的坑点
新手最容易踩三个坑:
- CSRF校验问题:用Vue/React做SPA时,要先请求
/sanctum/csrf-cookie获取CSRF Cookie,才能调用POST接口,不然会返回419错误——很多人忘这一步,调试半天找不到问题。 - Token永久有效:Sanctum默认的Token没有过期时间,除非用户主动登出(删Token),不然永远有效——如果需要限制过期,得自己手动加逻辑,或者用中间件控制。
- 不支持第三方应用:Sanctum没有授权流程,你没法让其他公司的APP用自己的账号登录你的API,比如你想给小程序开放自己的数据,Sanctum搞不定。
三、Passport:OAuth2授权码流程的专业方案
3.1 Passport是什么
再打比方:你用微信登录某外卖APP,点“微信登录”后跳转到微信的授权页,你同意后微信跳回APP,给你一个临时码,APP用这个码换自己的登录Token——微信全程不会拿到你的账号密码,这个就是OAuth2的授权码流程。Passport就是帮你快速实现这个流程的工具,严格遵循OAuth2.0标准,专门给第三方应用做认证。
示例:Passport实现OAuth2授权码流程(技术栈:Laravel 9 + Passport)
// 1. 安装Passport:composer require laravel/passport
// 2. 迁移生成OAuth相关表:php artisan migrate
// 3. 生成客户端:php artisan passport:install(会生成3个客户端:个人、密码、授权)
// 4. AuthServiceProvider里注册Passport路由:
// public function boot() { Passport::routes(); }
// User模型要引入HasApiTokens trait:
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable {
use HasApiTokens;
// ...其他代码
}
// 第三方应用授权流程示例:
// 步骤1:第三方APP跳转到你的授权页,让用户同意授权
// 地址:https://你的API域名/oauth/authorize?client_id=1&redirect_uri=https://第三方回调.com&response_type=code&scope=basic
// 步骤2:用户同意后,回调地址会返回临时code,比如:https://第三方回调.com?code=abc123
// 步骤3:第三方用code换Token(用Guzzle发送请求)
$http = new \GuzzleHttp\Client;
$response = $http->post('https://你的API域名/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '1', // 刚才生成的客户端ID
'client_secret' => 'xxxxxx', // 生成的客户端密钥
'redirect_uri' => 'https://第三方回调.com',
'code' => $code,
],
]);
$tokenData = json_decode((string)$response->getBody(), true);
// 步骤4:用access_token调用API
$apiResp = $http->get('https://你的API域名/api/user', [
'headers' => ['Authorization' => 'Bearer ' . $tokenData['access_token']]
]);
3.2 Passport的适用场景
适合对外提供的API,需要给第三方应用用:比如你的公司给其他小程序、第三方系统提供数据服务,需要严格的权限控制(给不同第三方开不同权限)、Token过期自动刷新(refresh_token),或者要对接其他系统的OAuth2认证,Passport是标准选择。
3.3 Passport的坑点
比Sanctum复杂得多,坑也更多:
- 配置复杂:要处理客户端、授权码、Token刷新、权限(scope),多了5张OAuth相关的表,维护成本高。
- Token有有效期:默认access_token是1小时,refresh_token是1年,要是没处理刷新Token的逻辑,用户用1小时就登不进去了,还要写刷新逻辑。
- 性能差:每次请求都要查OAuth的表验证Token,比Sanctum多了几次数据库查询,适合企业级场景,内部小项目没必要用。
- 密码客户端不推荐:php artisan passport:install生成的密码客户端,适合机器到机器的认证,但安全风险高,不要给用户用这个类型的客户端。
四、两者核心场景对比
我给你做个生活化的对比,一对比就懂:
- 你自己家的外卖小程序,内部开发,不用给别人用:选Sanctum,就像给自己家的钥匙,开门快,不用搞复杂的流程。
- 你家的外卖API要给其他第三方平台(比如美团、饿了么)用,让他们接入你的订单数据:选Passport,就像给别人发临时授权码,别人拿不到你的核心账号密码,安全合规。
- 无状态Token vs OAuth2授权码:Sanctum的Token是“你生成的专属钥匙”,自己用够了;Passport的Token是“标准授权的临时通行证”,给别人用必须符合规则。
五、选型总结
最后给你明确的选型规则,不用纠结:
- 选Sanctum的情况:API只给自己的前端(SPA、APP、内部后台)用,开发周期短,安全要求不高,不需要给第三方开放。
- 选Passport的情况:API要对外开放给第三方应用,需要严格的权限控制,Token要过期刷新,或者要遵循OAuth2行业标准。
- 千万别乱选:内部项目用Passport,会多维护一堆没用的OAuth表,配置到头疼;对外项目用Sanctum,第三方根本接不了,还要重改代码。
Comments