如何在Alfresco ADF v6.9.1与ACS v23.x中处理JWT会话过期?
在Alfresco ADF v6.9.1中实现JWT令牌自动刷新方案
针对你遇到的JWT令牌过期需手动重登的问题,ADF本身提供了内置的令牌自动刷新机制,也支持自定义扩展,以下是具体实现步骤:
一、使用ADF内置静默刷新机制
ADF的AuthModule原生支持基于OpenID Connect的静默令牌刷新,无需手动处理大部分逻辑,只需完成以下配置:
1. 配置认证参数
在环境配置文件(如src/environments/environment.ts)中添加或完善auth配置项:
export const environment = { production: false, auth: { issuer: 'https://你的ACS认证域名/auth/realms/alfresco', // ACS的Keycloak issuer地址 clientId: '你的ADF客户端ID', // 在Keycloak中创建的客户端ID scope: 'openid profile email', redirectUri: window.location.origin + '/auth/callback', silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html', // 静默刷新回调页 silentRefreshTimeout: 5000, // 刷新超时时间 timeoutFactor: 0.75, // 在令牌过期前75%的时间触发刷新 sessionChecksEnabled: true // 开启会话状态检查 } };
2. 创建静默刷新回调页
在项目根目录(或src/assets)创建silent-refresh.html文件,用于处理静默刷新的回调,避免页面跳转:
<!DOCTYPE html> <html> <body> <script> window.onload = function () { parent.postMessage(location.hash, location.origin); }; </script> </body> </html>
3. 导入并配置AuthModule
在AppModule中导入AuthModule并传入上述配置:
import { AuthModule } from '@alfresco/adf-core'; import { environment } from '../environments/environment'; @NgModule({ imports: [ // 其他模块... AuthModule.forRoot(environment.auth) ] }) export class AppModule { }
二、自定义令牌刷新逻辑(内置机制不满足时)
如果需要更灵活的控制(比如自定义错误处理、刷新时机),可以通过Angular拦截器扩展:
1. 实现自定义拦截器
创建token-refresh.interceptor.ts文件,捕获401错误并尝试刷新令牌:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http'; import { AuthService } from '@alfresco/adf-core'; import { Observable, throwError } from 'rxjs'; import { catchError, switchMap } from 'rxjs/operators'; @Injectable() export class TokenRefreshInterceptor implements HttpInterceptor { private isRefreshing = false; // 防止重复触发刷新 constructor(private authService: AuthService) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> { // 已登录时为请求添加令牌 if (this.authService.isLoggedIn()) { request = this.addTokenToRequest(request); } return next.handle(request).pipe( catchError((error: HttpErrorResponse) => { // 捕获401且未在刷新时,触发令牌刷新 if (error.status === 401 && !this.isRefreshing) { this.isRefreshing = true; return this.authService.refreshToken().pipe( switchMap(() => { this.isRefreshing = false; // 刷新成功后重新发起原请求 return next.handle(this.addTokenToRequest(request)); }), catchError(() => { this.isRefreshing = false; // 刷新失败则强制登出 this.authService.logout(); return throwError(() => new Error('令牌刷新失败,请重新登录')); }) ); } return throwError(() => error); }) ); } private addTokenToRequest(request: HttpRequest<any>): HttpRequest<any> { const token = this.authService.getToken(); return request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } }
2. 注册拦截器
在AppModule的providers中注册该拦截器:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { TokenRefreshInterceptor } from './interceptors/token-refresh.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: TokenRefreshInterceptor, multi: true } ] }) export class AppModule { }
三、关键注意事项
- 认证服务器配置:确保ACS的Keycloak客户端允许静默刷新,需将
silent-refresh.html添加到Valid Redirect URIs列表,客户端Access Type设为public或confidential。 - 令牌有效期设置:合理配置令牌的
expires_in时间,结合timeoutFactor确保刷新操作在令牌过期前触发。 - 测试验证:临时缩短令牌有效期(如5分钟),模拟用户闲置场景,验证自动刷新是否生效。
内容的提问来源于stack exchange,提问作者Varshil Shah
相关产品推荐
相关产品推荐

