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

如何配置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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:15:33