Laravel+Vue.js单页应用(SPA)需在何处进行身份认证?
Great question—this is a super common hurdle when transitioning from a traditional Laravel+Blade app to an SPA. Let’s break this down step by step:
1. PHP Backend (API Routes): Your Security Foundation
This is non-negotiable—all sensitive API endpoints must be protected by Laravel’s authentication middleware (like auth:sanctum or auth:api). Frontend code can always be tampered with, so your backend needs to validate every incoming request’s legitimacy on its own.
For example, define your protected API routes like this:
Route::middleware('auth:sanctum')->group(function () { Route::get('/api/user', fn (Request $request) => $request->user()); Route::put('/api/posts/{post}', [PostController::class, 'update']); // All other endpoints that require authentication });
2. Vue Frontend (Vue Router): For User Experience
While the backend handles actual security, Vue routes handle UI-level access control to keep unauthenticated users from seeing pages they shouldn’t. Use Vue Router’s navigation guards to check login status before navigating to protected routes.
Here’s a quick example:
// In your router setup router.beforeEach((to, from, next) => { const isLoggedIn = localStorage.getItem('auth_token') !== null; // Check if the route requires auth and user isn't logged in if (to.meta.requiresAuth && !isLoggedIn) { next('/login'); } else { next(); } }); // And mark routes as protected in your route config const routes = [ { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true } }, { path: '/login', component: Login }, ];
1. Session Management: Use Laravel Sanctum (Recommended)
If you were using Laravel’s default session auth, Sanctum is the perfect drop-in for SPAs—it’s built specifically for this use case:
- Set up Sanctum on the backend, then create a login endpoint that returns an auth token (or use cookie-based auth, which is more secure for same-domain SPAs).
- Store the token in
localStorageor a secure cookie on the frontend, then attach it to every API request (use an Axios interceptor to automate this):axios.interceptors.request.use(config => { const token = localStorage.getItem('auth_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); - Backend session logic works just like before—
Auth::user()will still return the authenticated user, and session expiration is handled by Sanctum’s token settings.
2. Permissions: Frontend UI Checks + Backend Enforcement
Never rely solely on frontend permission checks—the backend must validate permissions for every sensitive action. But frontend checks improve UX by hiding unavailable actions or routes.
Backend (Keep Using Laravel Gates/Policies)
Continue using Laravel’s built-in Gates or Policies to enforce permissions on the server side:
// In your PostController public function update(Post $post) { // Use a Policy to verify the user can update this post $this->authorize('update', $post); // Proceed with the update logic }
Frontend (Cache & Check Permissions)
After login, fetch the user’s permissions from an API endpoint (e.g., /api/user/permissions) and store them in a state management tool like Pinia or Vuex. Then use this data to conditionally render UI elements:
<template> <div> <button v-if="can('update_post')" @click="editPost">Edit Post</button> </div> </template> <script setup> import { useUserStore } from '@/stores/user'; const userStore = useUserStore(); const can = (permission) => { return userStore.permissions.includes(permission); }; </script>
3. Handling Session Expiration
Set up an Axios response interceptor to catch 401 Unauthorized errors, clear the local token, and redirect to the login page:
axios.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { localStorage.removeItem('auth_token'); router.push('/login'); } return Promise.reject(error); } );
内容的提问来源于stack exchange,提问作者Felipe Paz

