如何配置Spring Gateway后的Angular应用并实现身份验证检查?
Angular前端集成网关与Keycloak实现路由安全及令牌转发
一、核心思路
基于你现有的网关+Keycloak+后端服务架构,Angular端需要完成三个核心动作:路由权限控制、从网关获取并管理JWT、自动将令牌转发至后端。
二、步骤实现
1. 路由安全配置(AuthGuard)
通过Angular的路由守卫实现页面访问控制,未认证用户自动跳转网关授权。
- 创建AuthGuard服务:
import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(): boolean { if (this.authService.isAuthenticated()) { return true; } // 重定向到网关的Keycloak授权页面,回调地址指向Angular的callback路由 window.location.href = 'http://your-gateway-domain/auth/keycloak/login?redirect_uri=http://your-angular-domain/callback'; return false; } }
- 在路由配置中添加守卫:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ProtectedComponent } from './protected/protected.component'; import { AuthGuard } from './auth.guard'; import { CallbackComponent } from './callback/callback.component'; const routes: Routes = [ { path: '', component: HomeComponent }, // 受保护路由添加AuthGuard { path: 'protected', component: ProtectedComponent, canActivate: [AuthGuard] }, // 网关授权回调路由 { path: 'callback', component: CallbackComponent }, { path: '**', redirectTo: '' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
2. JWT获取与管理(AuthService)
封装服务处理令牌的存储、校验、获取逻辑。
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { private tokenStorageKey = 'auth_jwt_token'; // 校验用户是否已认证(检查令牌是否存在且未过期) isAuthenticated(): boolean { const token = localStorage.getItem(this.tokenStorageKey); if (!token) return false; // 解析JWT payload校验过期时间 const payload = JSON.parse(atob(token.split('.')[1])); return payload.exp > Date.now() / 1000; } // 获取令牌 getToken(): string | null { return localStorage.getItem(this.tokenStorageKey); } // 存储令牌 setToken(token: string): void { localStorage.setItem(this.tokenStorageKey, token); } // 退出登录 logout(): void { localStorage.removeItem(this.tokenStorageKey); // 跳转到网关的退出接口,清除Keycloak会话 window.location.href = 'http://your-gateway-domain/auth/logout'; } }
3. 回调处理(CallbackComponent)
接收网关授权成功后的回调,获取令牌并跳转到受保护页面。
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Component({ selector: 'app-callback', template: '<div>登录中,请稍候...</div>' }) export class CallbackComponent implements OnInit { constructor( private route: ActivatedRoute, private authService: AuthService, private router: Router ) {} ngOnInit(): void { this.route.queryParams.subscribe(params => { const token = params['token']; // 网关授权成功后返回的令牌参数 if (token) { this.authService.setToken(token); // 跳转到默认受保护页面 this.router.navigate(['/protected']); } else { this.router.navigate(['/']); } }); } }
4. 自动转发令牌到后端(HTTP拦截器)
通过拦截器给所有后端请求自动添加Authorization头。
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http'; import { AuthService } from './auth.service'; @Injectable() export class TokenInterceptor implements HttpInterceptor { constructor(private authService: AuthService) {} intercept(req: HttpRequest<any>, next: HttpHandler) { const token = this.authService.getToken(); if (token) { // 克隆请求并添加Authorization头 const authRequest = req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) }); return next.handle(authRequest); } return next.handle(req); } }
- 在AppModule中注册拦截器:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { TokenInterceptor } from './token.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true } ] }) export class AppModule { }
三、关键配置注意事项
- 网关CORS配置:允许Angular域名的请求,开启
allowCredentials,确保Cookie或令牌能正常传递。 - Keycloak客户端配置:将Angular的回调地址(如
http://your-angular-domain/callback)添加到Keycloak客户端的"Valid Redirect URIs"列表中。 - 令牌存储建议:如果追求更高安全性,建议网关将JWT存储在HttpOnly Cookie中,Angular请求时开启
withCredentials: true,无需手动存储令牌,避免XSS风险。 - 令牌过期处理:可在AuthService中添加定时检查逻辑,令牌过期前自动触发网关的刷新令牌接口,或跳转到重新授权页面。
内容的提问来源于stack exchange,提问作者Daniel Stiefel
相关产品推荐
相关产品推荐

