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

如何用Laravel中间件保护Angular中的管理员专属路由?

如何用Laravel保护Angular的管理员专属路由

这个问题在前后端分离项目里太普遍了,前端路由没法直接套用Laravel的中间件,但我们可以结合「前端路由守卫+后端权限校验」的方式来实现,给你分享几个实用的方案:

方案一:JWT + Angular路由守卫(最常用)

这个方案适合JWT作为身份验证方式的场景,核心思路是把用户的权限信息(比如是否是管理员)塞进JWT里,前端通过解析JWT做路由拦截,同时后端API再做一层兜底校验。

1. Laravel端:在JWT中携带权限信息

如果你用的是tymon/jwt-auth包,可以在User模型里自定义JWT的payload字段,把管理员标识加进去:

// app/Models/User.php
public function getJWTCustomClaims()
{
    return [
        'is_admin' => $this->is_admin, // 假设你的用户表有is_admin字段
        'user_id' => $this->id
    ];
}

登录接口返回JWT后,前端把token存在localStorage或者sessionStorage里。

2. Angular端:创建管理员专属路由守卫

生成一个AdminGuard守卫,在进入受保护路由前解析JWT,判断用户是否是管理员:

// src/app/guards/admin.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { JwtHelperService } from '@auth0/angular-jwt';

@Injectable({ providedIn: 'root' })
export class AdminGuard implements CanActivate {
  constructor(private jwtHelper: JwtHelperService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {
    const token = localStorage.getItem('auth_token');
    
    // 先判断token是否过期或不存在
    if (!token || this.jwtHelper.isTokenExpired(token)) {
      this.router.navigate(['/login']);
      return false;
    }

    // 解析token里的管理员标识
    const decodedToken = this.jwtHelper.decodeToken(token);
    if (!decodedToken.is_admin) {
      this.router.navigate(['/403']); // 跳转到无权限页面
      return false;
    }

    return true;
  }
}

然后在路由配置中给需要保护的页面绑定这个守卫:

// src/app/app-routing.module.ts
const routes: Routes = [
  // 其他路由...
  {
    path: 'posts/create',
    component: PostCreateComponent,
    canActivate: [AdminGuard]
  },
  {
    path: 'posts/edit/:id',
    component: PostEditComponent,
    canActivate: [AdminGuard]
  }
];

3. 关键:后端API必须加权限校验

前端守卫只是防君子不防小人,一定要在Laravel的API接口层再加一层校验。比如创建一个AdminMiddleware:

// app/Http/Middleware/AdminMiddleware.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AdminMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        if (!auth()->user() || !auth()->user()->is_admin) {
            return response()->json(['message' => '无权限执行此操作'], 403);
        }

        return $next($request);
    }
}

在app/Http/Kernel.php里注册这个中间件:

protected $routeMiddleware = [
    // 其他中间件...
    'admin' => \App\Http\Middleware\AdminMiddleware::class,
];

最后给需要保护的API接口绑定这个中间件:

// routes/api.php
Route::post('/posts', [PostController::class, 'store'])->middleware('auth:api', 'admin');
Route::put('/posts/{id}', [PostController::class, 'update'])->middleware('auth:api', 'admin');

方案二:后端返回权限列表,Angular动态生成路由

如果你的权限规则更复杂(比如不同角色有不同的路由权限),可以让Laravel返回当前用户的可访问权限列表,Angular根据这个列表动态生成路由。

1. Laravel端:提供权限查询接口

// routes/api.php
Route::get('/user/permissions', function () {
    $user = auth()->user();
    $permissions = [];

    if ($user->is_admin) {
        $permissions = ['posts.create', 'posts.edit', 'posts.delete'];
    }

    return response()->json(['permissions' => $permissions]);
})->middleware('auth:api');

2. Angular端:动态加载路由

在应用初始化时调用权限接口,根据返回的权限添加路由:

// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './services/auth.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  constructor(private router: Router, private authService: AuthService) {}

  ngOnInit(): void {
    this.authService.getUserPermissions().subscribe(permissions => {
      const currentRoutes = this.router.config;

      // 根据权限添加路由
      if (permissions.includes('posts.create')) {
        currentRoutes.push({
          path: 'posts/create',
          component: () => import('./posts/post-create/post-create.component').then(m => m.PostCreateComponent)
        });
      }

      if (permissions.includes('posts.edit')) {
        currentRoutes.push({
          path: 'posts/edit/:id',
          component: () => import('./posts/post-edit/post-edit.component').then(m => m.PostEditComponent)
        });
      }

      // 更新路由配置
      this.router.resetConfig(currentRoutes);
    });
  }
}

同样,后端API的权限校验不能少。

方案三:Laravel Sanctum + 后端校验接口(适合同域SPA)

如果你的Angular项目和Laravel后端是同域的,用Sanctum会更省心,它基于Cookie做身份验证,不需要手动处理JWT。

1. Laravel端:配置Sanctum并创建校验接口

先配置好Sanctum的SPA支持,然后创建一个接口专门用来校验用户是否是管理员:

// routes/api.php
Route::get('/check-admin', function () {
    return response()->json(['is_admin' => auth()->user()->is_admin]);
})->middleware('auth:sanctum', 'admin');

2. Angular端:路由守卫调用后端校验接口

在守卫里直接请求这个接口,根据返回结果判断是否允许访问:

// src/app/guards/admin.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { map, catchError } from 'rxjs/operators';
import { of } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class AdminGuard implements CanActivate {
  constructor(private http: HttpClient, private router: Router) {}

  canActivate() {
    return this.http.get('/api/check-admin').pipe(
      map(() => true),
      catchError(() => {
        this.router.navigate(['/403']);
        return of(false);
      })
    );
  }
}

核心原则

不管用哪个方案,一定要记住:前端路由守卫只是优化用户体验,真正的权限控制必须在后端API层实现,因为前端的任何限制都可以被开发者工具绕过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:07:33