Laravel 用 Sanctum 做 SPA 鉴权:令牌签发、多 guard 与前端配合

test12026-09-261 次阅读

Sanctum 的两种模式

Sanctum 同时支持"令牌(token)"和"会话(session cookie)"两套机制。SPA 与第一方前端走的是会话模式:前端和 API 同域(或配好 CORS),登录后由后端下发 CSRF cookie,之后请求带 X-XSRF-TOKEN 即可,不需要在请求头里塞 Bearer token。

后端配置

先在 config/cors.php 放开凭据,并允许前端源;config/sanctum.php 的 guard 用 web 即可复用会话驱动。

// config/cors.php 关键项
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:5173'],
'supports_credentials' => true,
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/sanctum/csrf-cookie', function () {
    return response()->noContent();
});

Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/user', fn (Request $r) => $r->user());

登录签发会话

public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    if (! auth()->attempt($credentials)) {
        return response()->json(['message' => '账号或密码错误'], 422);
    }
    $request->session()->regenerate();   // 防会话固定
    return response()->noContent();
}

前端配合

axios 需开启 withCredentials,并在调用任何受保护接口前先请求一次 CSRF cookie。

// 进入应用时先拿 cookie
await axios.get('/sanctum/csrf-cookie', { withCredentials: true });

// 之后所有请求带凭据
axios.defaults.withCredentials = true;
await axios.post('/api/login', { email, password });
const { data: user } = await axios.get('/api/user');

多 guard 与令牌能力

若系统里还有移动端或第三方需要长期令牌,可保留 auth:sanctum 的 token 能力:$user->createToken('mobile') 生成 Bearer token,前端 SPA 仍走 cookie 会话,两者共用同一套中间件互不冲突。注意 CSRF cookie 接口必须放在 web 中间件组(默认 sanctum/csrf-cookie 已在其中),否则 cookie 不会下发。

  • 同域 SPA 优先用会话模式,天然防 CSRF,无需前端管理 token 过期。
  • 跨域时务必 supports_credentials=true 且前端 withCredentials,否则 cookie 不生效。
  • 退出登录调用 auth()->guard('web')->logout() 并销毁会话。
T

test1

文章作者

Sanctum 的两种模式 Sanctum 同时支持"令牌(token)"和"会话(session cookie)"两...

分类
技术
发布时间
2026-09-26
字数
约 1824 字
阅读
1 次