如何在Laravel Vue单页应用中使用Cartalyst Sentinel进行权限校验?
Hey there! I’ve tackled this exact issue when building Laravel+Vue SPAs with Sentinel, so let me break down a few practical, battle-tested approaches to solve this:
1. Pass User Permissions to the Frontend (Most Common Approach)
The core idea is to send the authenticated user’s permissions/roles to the frontend during login, then store and use that data for client-side checks.
Step 1: Update Your Backend Login Response
Modify your login controller to include the user’s permissions in the JSON response:
public function login(Request $request) { // Validate login credentials first $credentials = $request->only('email', 'password'); if ($user = Sentinel::authenticate($credentials)) { // Get the user's direct permissions (or combine with role permissions) $permissions = $user->getPermissions()->toArray(); // If you use roles, fetch role-based permissions like this: // $permissions = $user->roles->flatMap(fn($role) => $role->permissions)->toArray(); // Return token, user data, and permissions return response()->json([ 'token' => $user->createToken('SPA')->plainTextToken, 'user' => $user, 'permissions' => $permissions ]); } return response()->json(['error' => 'Invalid credentials'], 401); }
Step 2: Store Permissions in Vuex (or LocalStorage)
Once the frontend receives the login response, save the permissions to your Vue store for global access:
// In your login component's success handler async handleLogin() { try { const response = await axios.post('/api/login', this.loginForm); this.$store.commit('SET_USER', response.data.user); this.$store.commit('SET_PERMISSIONS', response.data.permissions); // Redirect to dashboard, etc. } catch (err) { // Handle login errors } }
Step 3: Create Reusable Permission Helpers
Add a global method and/or custom directive to Vue to make permission checks easy:
// In main.js Vue.prototype.$hasAccess = function(permission) { // Adjust this based on how your permissions are structured (array vs key-value) return this.$store.state.permissions.includes(permission); // For key-value permissions (e.g., { manage_users: true }) use: // return !!this.$store.state.permissions[permission]; }; // Custom directive to hide elements users don't have access to Vue.directive('has-access', { inserted(el, binding) { const hasPermission = Vue.prototype.$hasAccess(binding.value); if (!hasPermission) { el.style.display = 'none'; // For a more permanent removal: el.parentNode?.removeChild(el); } } });
Usage Examples
<!-- In templates --> <button v-has-access="manage_users">Edit User</button> <a v-has-access="create_post" href="/posts/new">Create Post</a> <!-- In script logic --> methods: { async deletePost() { if (this.$hasAccess('delete_post')) { // Execute delete request } else { alert("You don't have permission to delete this post"); } } }
2. Backend Validation for Critical Actions (Extra Security)
Frontend checks can be bypassed, so for sensitive operations (like deleting data), always validate permissions on the backend too. You can also add a dedicated endpoint for frontend permission checks:
Backend Endpoint
Route::get('/api/check-permission/{permission}', function($permission) { if (!Sentinel::check()) { return response()->json(['allowed' => false], 401); } return response()->json(['allowed' => Sentinel::hasAccess($permission)]); });
Frontend Helper Method
// In a utility file or Vue prototype async checkPermission(permission) { try { const response = await axios.get(`/api/check-permission/${permission}`); return response.data.allowed; } catch (err) { return false; } }
Usage for Critical Actions
async deletePost() { const canDelete = await this.checkPermission('delete_post'); if (canDelete) { // Proceed with delete request await axios.delete(`/api/posts/${this.post.id}`); } else { this.$notify.error("You're not allowed to perform this action"); } }
3. Route Guarding for Page Access
Control access to entire Vue routes using router guards:
// In router/index.js router.beforeEach((to, from, next) => { const requiredPermission = to.meta.permission; if (requiredPermission) { const hasAccess = store.state.permissions.includes(requiredPermission); if (hasAccess) { next(); } else { next('/forbidden'); // Redirect to a "no access" page } } else { next(); } }); // Route configuration example { path: '/users', name: 'UserManagement', component: () => import('../views/UserManagement.vue'), meta: { permission: 'manage_users' } }
内容的提问来源于stack exchange,提问作者Fahim Hasan

