Laravel Sanctum + Vue3 登录后/api/user接口401未授权问题求助
Laravel Sanctum + Vue3 401未授权问题排查与解决
问题现象
登录后调用http://localhost:8000/api/user(GET请求)返回401状态码,但数据库personal_access_tokens表已生成对应令牌,Postman手动携带令牌调用该接口可正常获取用户信息。
相关配置
Laravel路由配置
<?php Route::prefix('auth')->group(function () { Route::post('/login', LoginController::class); Route::post('/logout', LogoutController::class)->middleware('auth:sanctum'); Route::post('/register', RegisterController::class); }); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); });
LoginController代码
<?php class LoginController extends Controller { public function __invoke(LoginRequest $request){ $user = User::where('email', $request->email)->first(); if(!$user || !Hash::check($request->password, $user->password)){ throw ValidationException::withMessages([ 'email' => ['The credentials you entered are incorrect.'] ]); } return response()->json([ 'user' => $user, 'token' => $user->createToken('laravel_api_token')->plainTextToken ]); } }
CORS配置
<?php return [ 'paths' => ['api/*', 'sanctum/csrf-cookie', 'auth/*'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true, ];
Sanctum配置
return [ 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:5173,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', Sanctum::currentApplicationUrlWithPort() ))), ];
.env中的Stateful Domains配置
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8000,localhost:3000,localhost:5173,127.0.0.1,127.0.0.1:8000,127.0.0.1:5173,::1
Vue3 API调用代码
import api from "./api"; export const csrfCookie = () => api.get("/sanctum/csrf-cookie"); export const login = (credentials) => api.post("/api/auth/login", credentials); export const register = (user) => api.post("/api/auth/register", user); export const logout = () => api.post("/api/auth/logout"); console.log(login); export const getUser = () => api.get("/api/user");
Vue3 Pinia Auth Store代码
import { defineStore } from "pinia"; import { computed, ref } from "vue"; import { csrfCookie, login, register, logout, getUser } from "../http/auth-api"; export const useAuthStore = defineStore("authStore", () => { const user = ref(null); const isLoggedIn = computed(() => !!user.value); const fetchUser = async () => { const { data } = await getUser(); user.value = data; }; const handleLogin = async (credentials) => { await csrfCookie(); await login(credentials); await fetchUser(); }; const handleRegister = async (newUser) => { await register(newUser); await handleLogin({ email: newUser.email, password: newUser.password, }); }; const handleLogout = async () => { await logout(); user.value = null; }; return { user, isLoggedIn, fetchUser, handleLogin, handleRegister, handleLogout, }; });
Axios配置
axios.defaults.withCredentials = true; const api = axios.create({ baseURL: import.meta.env.VITE_BASE_URL, }) export default api
解决方案
核心问题:前端未自动携带令牌到请求头
Postman手动携带令牌能成功,但你的前端代码仅在登录时获取了令牌,却未配置自动将令牌附加到请求头中。
存储登录返回的令牌
修改Pinia的handleLogin方法,将返回的令牌存入本地存储:const handleLogin = async (credentials) => { await csrfCookie(); const { data } = await login(credentials); localStorage.setItem('api_token', data.token); await fetchUser(); };配置Axios请求拦截器自动携带令牌
修改Axios配置,添加请求拦截器,为每个请求自动带上Authorization头:axios.defaults.withCredentials = true; const api = axios.create({ baseURL: import.meta.env.VITE_BASE_URL, }) api.interceptors.request.use(function (config) { const token = localStorage.getItem('api_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, function (error) { return Promise.reject(error); }); export default api登出时清除本地令牌
修改Pinia的handleLogout方法,清除存储的令牌:const handleLogout = async () => { await logout(); user.value = null; localStorage.removeItem('api_token'); };
额外检查项
- 确认
VITE_BASE_URL环境变量值正确(如http://localhost:8000) - 清除浏览器缓存,避免旧Cookie或令牌干扰请求
- 确认前端运行端口已包含在Sanctum的
stateful配置中(你的配置已覆盖常用端口,无需修改) - 确认CORS配置的
supports_credentials为true(你的配置已满足)
内容的提问来源于stack exchange,提问作者user22809416
相关产品推荐
相关产品推荐

