You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置Bearer令牌后Sanctum返回未认证(401)问题求助

问题分析

你遇到的核心问题是:自定义中间件解密Cookie后设置的Authorization头,未被Sanctum的auth:sanctum中间件正确识别。虽然移除auth:sanctum后能确认请求头存在,但Sanctum的认证逻辑可能因请求头读取时机、缓存机制,或是你的设置方式问题,无法捕获到该头信息。

解决方案

以下是几种可行的修复方案,按优先级排序:

方案1:手动在中间件中完成用户认证(推荐)

跳过设置Authorization头的步骤,直接在自定义中间件中通过解密后的token找到用户并绑定到请求对象,让Sanctum直接识别已认证用户:

修改DecryptSanctumTokenMiddleware代码:

use Laravel\Sanctum\PersonalAccessToken;

public function handle(Request $request, Closure $next): Response
{
    $encryptedToken = $request->cookie('token');

    if (!$encryptedToken) {
        return $this->failedRequest('', 'Unauthenticated', 401);
    }

    try {
        $decryptedToken = Crypt::decryptString($encryptedToken);
    } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
        return $this->failedRequest('', 'Invalid token', 401);
    }

    // 查找对应的Sanctum令牌
    $token = PersonalAccessToken::findToken($decryptedToken);

    if (!$token || $token->expired()) {
        return $this->failedRequest('', 'Unauthenticated', 401);
    }

    // 将用户绑定到请求对象
    $request->setUserResolver(function () use ($token) {
        return $token->tokenable;
    });

    return $next($request);
}

修改后,auth:sanctum中间件会直接识别请求中已绑定的用户,无需依赖Authorization头。

方案2:确保Authorization头被Sanctum正确读取

若坚持通过设置Authorization头认证,可同时更新请求的服务器参数(Sanctum的bearerToken()方法会优先从$_SERVER读取):

修改中间件中设置头的代码段:

// 同时设置请求头和服务器参数
$request->headers->set("Authorization", "Bearer $decryptedToken");
$request->server->set('HTTP_AUTHORIZATION', "Bearer $decryptedToken");

Sanctum的TokenGuard获取token时,会优先检查$_SERVER['HTTP_AUTHORIZATION'],直接设置该参数可确保token被正确捕获。

方案3:检查Cookie属性配置

确认登录时设置的Cookie属性符合运行环境要求:

  • 若应用在HTTPS环境下,需将Cookie的secure参数设为true,否则浏览器可能不在HTTPS请求中携带Cookie:
$cookie = Cookie::make('token', $encryptedToken, 60, null, null, env('APP_ENV') === 'production', true);
  • 若为跨域请求,需设置SameSite为'none'并配合secure=true(Laravel 8+支持):
$cookie = Cookie::make('token', $encryptedToken, 60, null, null, env('APP_ENV') === 'production', true, false, 'none');
验证步骤
  1. 在自定义中间件中添加调试代码,确认解密后的token格式正确(应为Sanctum生成的明文格式,如xxx|xxx):
dd($decryptedToken);
  1. 验证PersonalAccessToken::findToken($decryptedToken)能正确返回令牌模型,且$token->tokenable是对应的用户实例。

内容的提问来源于stack exchange,提问作者henrbu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:17:42