Laravel 10中Web与API用户的Bearer Token及用户ID获取最佳实践
针对Laravel Sanctum多端用户ID获取的最佳实践
方案1的合理性分析
你倾向的**方案1(为Web用户创建永不过期Bearer Token)**其实存在优化空间:
Laravel Sanctum的auth:sanctum中间件本身就同时支持Web端的会话认证和API客户端的Token认证——当Web用户通过Jetstream/Fortify登录后,不需要手动生成永不过期Token,直接通过auth()->user()->id就能拿到用户ID,这是Sanctum原生支持的能力。手动生成永不过期Token反而会带来安全隐患(Token泄露后无法主动失效),完全没必要。
方案3的安全隐患与可行验证方式
如果一定要选择方案3(传递用户ID参数),要确保只有本Web应用能合法传递,核心是通过签名验证请求合法性:
- Web端在发起请求时,用应用密钥对用户ID进行签名:
// Web端生成签名 $userId = auth()->id(); $signature = hash_hmac('sha256', $userId, config('app.key')); // 请求API时携带user_id和signature两个参数 - API端接收请求后验证签名:
这种方式依赖只有你的应用知晓的密钥生成签名,外部客户端或Postman无法伪造有效签名,能确保请求合法性。但本质上方案3属于冗余设计,因为Sanctum已经能自动识别用户身份。$userId = request()->input('user_id'); $signature = request()->input('signature'); $validSignature = hash_hmac('sha256', $userId, config('app.key')); if (!hash_equals($signature, $validSignature)) { abort(403, '非法请求'); }
更优的原生实现方案
利用Sanctum的原生特性就能完美解决问题,无需额外方案:
- 路由中间件按需配置:
- 允许访客访问的路由(如
sample接口),仅保留api中间件即可:Route::group(['middleware' => ['api']], function () { Route::get('sample', [ApiController::class, 'sample'])->name('api.sample'); // 未登录时auth()->user()为null,业务逻辑自行处理访客场景 }); - 需要登录用户(Web或API客户端)访问的路由(如
download接口),保留auth:sanctum中间件:Route::group(['middleware' => ['auth:sanctum']], function () { Route::get('download', [DownloadController::class, 'download'])->name('api.download'); });
- 允许访客访问的路由(如
- 统一获取用户ID:
在API控制器中,直接通过auth()->user()?->id获取用户ID——不管是Web端登录用户(会话认证)还是API客户端(Bearer Token认证),Sanctum都会自动解析出对应的用户实例,无需区分场景。
总结
- 优先采用Sanctum原生双认证机制,代码简洁且安全,完全不需要额外生成Token或传递用户ID。
- 方案1手动生成永不过期Token存在安全风险,不推荐;方案3冗余且需额外做签名验证,无必要。
- 核心原则:利用Laravel Sanctum内置的会话+Token双认证能力,统一处理Web和API客户端的用户身份识别。
内容的提问来源于stack exchange,提问作者Shaho
相关产品推荐
相关产品推荐

