Laravel与Angular集成项目JWT认证受保护路由未授权访问问题求解
解决方案
你需要同时调整Laravel后端路由权限校验和Angular前端路由守卫两部分逻辑,具体步骤如下:
1. 后端Laravel配置
你当前的所有路由都只挂载了api中间件,没有添加JWT授权校验的中间件,需要把需要登录才能访问的路由放到auth:api中间件组中,调整后的api.php代码如下:
Route::group([ 'middleware' => 'api', 'prefix' => 'auth' ], function ($router) { // 公开路由,无需登录即可访问 Route::post('/signup', [JwtAuthController::class, 'register']); Route::post('/signin', [JwtAuthController::class, 'login']); Route::post('/req-password-reset', [ResetPwdReqController::class, 'reqForgotPassword']); Route::post('/update-password', [UpdatePwdController::class, 'updatePassword']); // 需登录校验的私有路由,加auth:api中间件 Route::group(['middleware' => 'auth:api'], function () { Route::get('/user', [JwtAuthController::class, 'user']); Route::post('/token-refresh', [JwtAuthController::class, 'refresh']); Route::post('/signout', [JwtAuthController::class, 'signout']); // 其他需要权限控制的接口都统一放到这个组内 }); });
配置完成后,未携带有效JWT Token访问私有接口时,后端会自动返回401 Unauthorized状态码。
2. 前端Angular配置
跳转登录页的逻辑需要在前端实现,建议添加两层校验:
2.1 添加路由守卫
给需要登录的路由(比如user-profile)添加路由守卫,访问前先判断本地是否存储了有效JWT Token,无有效Token则直接跳转登录页:
// auth.guard.ts import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private router: Router) {} canActivate(): boolean { const token = localStorage.getItem('jwt_token'); if (token) return true; this.router.navigate(['/login']); return false; } }
然后在路由配置中给对应路由绑定守卫:
// app-routing.module.ts const routes: Routes = [ // 公开路由 { path: 'login', component: LoginComponent }, { path: 'signup', component: SignupComponent }, // 需登录校验的路由 { path: 'user-profile', component: UserProfileComponent, canActivate: [AuthGuard] } ];
2.2 添加HTTP拦截器
统一处理所有接口返回的401状态码,覆盖Token过期但本地仍有存储的场景,遇到401状态码时自动清除本地存储的Token并跳转登录页:
// auth.interceptor.ts import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { Router } from '@angular/router'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private router: Router) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { const token = localStorage.getItem('jwt_token'); // 自动给请求添加Authorization请求头 if (token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next.handle(request).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 401) { localStorage.removeItem('jwt_token'); this.router.navigate(['/login']); } return throwError(() => error); }) ); } }
最后把拦截器注册到app.module.ts的providers数组中即可生效。
内容的提问来源于stack exchange,提问作者user3653474
相关产品推荐
相关产品推荐

