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

Laravel 8 Sanctum鉴权遇503错误:跨域Postman调用失败求助

Laravel 8 Sanctum 调用API返回503 Service Unavailable问题

我在Laravel 8中配置好了Sanctum,数据库里也能生成personal_access_tokens,但用Postman携带Bearer Token调用API时一直返回503 Service Unavailable。已经确认服务器不在维护模式(执行过php artisan up),因为是跨设备调用(Postman测试,后续是Windows设备向网站传数据),怀疑是stateful配置的问题,卡了4天没解决。

相关配置代码

api.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\V2\Api\KeywordsController;


Route::middleware(['auth:sanctum', 'abilities:db:view,db:update,db:store'])->group(function () {
        Route::get('fetch-keyword', [KeywordsController::class, 'fetchKeyword']);
        Route::put('update-keyword/{keywordName}', [KeywordsController::class, 'updateKeyword']);
});

auth.php

<?php

return [

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
            'hash' => false,
        ],
    ],


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

    ],

    'verification' => [
        'expire' => 1440,
    ],


    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 180,
            'throttle' => 60,
        ],
    ],

    'password_timeout' => 10800,

];

sanctum.php

<?php

use Laravel\Sanctum\Sanctum;

return [

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),


 'guard' => ['api'],

    'expiration' => null,

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],

];

User模型

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Paddle\Billable;
use Spatie\Permission\Traits\HasRoles;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable, Billable, HasRoles;

.....more code not attached

Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];


    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,
        'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
    ];
}

Token生成逻辑

public function update(Request $request, $id)
{
    $validator = Validator::make($request->all(), [
        'name' => 'required|string|max:255',
        'email' => ['required', Rule::unique('users')->ignore($id)],
        'has_token' => 'nullable|boolean',
        'password' => $request->filled('password') ? 'required|min:8' : '',
        'token_name' => [
            'nullable',
            'string',
            Rule::requiredIf(function () use ($request) {
                return $request->has_token === 1;
            }),
        ],
    ]);

    if ($validator->fails()) {
        return response()->json(['errors' => $validator->errors()], 422);
    }

    try {
        $user = User::find($id);

        if ($request->email !== $user->email) {
            return $this->changeEmail($request->email, $request->password, $id);
        }

        // Update fields
        $user->name = $request->name;
        $user->current_credits = $request->current_credits;

        if ($request->filled('password')) {
            $user->password = Hash::make($request->password);
        }

        $user->save();

        $user = User::where('email', $request->email)->first();
        if ($request->has_token === 1 && $request->filled('token_name')) {
            $user->createToken($request->token_name, ['db:view', 'db:update', 'db:store']);
        } elseif ($request->has_token === 0) {
            $user->tokens()->delete(); 
        }

    } catch (Exception $e) {
        return response()->json(['error' => $e->getMessage()], 500);
    }

    return response()->json(['success' => 'success'], 200);
}

排查建议

  1. 查看服务器日志:503属于服务器层面错误,优先检查Nginx/Apache的错误日志,以及Laravel storage/logs目录下的日志,定位具体报错原因。
  2. 调整Sanctum Stateful配置:跨设备调用不属于stateful场景,在.env中设置SANCTUM_STATEFUL_DOMAINS=为空,同时确保SESSION_DOMAIN配置正确(本地测试可设为localhost或空)。
  3. 修正API中间件:当前api中间件组中ThrottleRequests重复,删除throttle:60,1,保留\Illuminate\Routing\Middleware\ThrottleRequests::class.':api'避免冲突。
  4. 验证Token格式与权限:确认Postman请求头Authorization格式为Bearer {token},且该Token关联用户拥有db:view,db:update,db:store权限。
  5. 测试基础路由:创建一个不带auth:sanctum和abilities的测试API,验证服务器是否能正常响应,排除路由或服务器基础配置问题。
  6. 清除缓存:执行php artisan config:clear、php artisan cache:clear、php artisan route:clear确保配置生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:45:53