angular - 刷新令牌角
问题描述
我创建了一个用于从我的 Angular 应用程序调用 API 的服务。在该服务中,我声明了 ROOT_URL 和 TOKEN 变量并为它们赋值。
在声明下方,使用上述 ROOT_URL 和 TOKEN 的 API 获取方法很少。
我面临的问题是,此 TOKEN 值每 24 小时过期一次,因此我必须每天更改该值。我使用以前的 TOKEN 通过邮递员获取刷新令牌。
有人可以给我一个解决方案,我该如何实现这将在每次 TOKEN 到期时自动发生?
解决方案
通常,来自 API 的 HTTP 响应标头包含一些内容,表明该客户端曾经通过身份验证,但现在有一个过期的令牌。通常,响应标头具有称为 token-expired 或 www-authenticate 的属性;您必须在开始刷新令牌过程之前检查这一点。
代码示例:
身份验证拦截器
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
HttpErrorResponse
} from '@angular/common/http';
import { AuthService } from '../services/auth.service';
import { Observable, BehaviorSubject, throwError } from 'rxjs';
import { environment } from 'src/environments/environment';
import { filter, switchMap, take, catchError } from 'rxjs/operators';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private tryingRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(public authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.authService.getToken();
request = this.addAuthorization(request, token);
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
const tokenExpired = error.headers.get('token-expired');
if (tokenExpired) {
return this.handle401Error(request, next);
}
this.authService.logout();
return throwError(error);
} else {
return throwError(error);
}
}));
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.tryingRefreshing) {
this.tryingRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {
this.tryingRefreshing = false;
this.refreshTokenSubject.next(token);
return next.handle(this.addAuthorization(request, token));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addAuthorization(request, jwt));
}));
}
}
addAuthorization(httpRequest: HttpRequest<any>, token: string) {
return httpRequest = httpRequest.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
}
}
刷新令牌
这只是展示 share() 方法的示例方法。
refreshToken(): Observable<string> {
return this.http.post<any>(`${this.baseUrl}/auth/token/refresh-token`, {}, { withCredentials: true })
.pipe(
share(),
map((authResponse) => {
this.currentAuthSubject.next(authResponse);
this.addToLocalStorage(authResponse);
return authResponse.token;
}));
}
推荐阅读
- python - 我不知道为什么我对 django 的看法没有显示在浏览器上
- python - 如何在 matplotlib 中跨 twinx 控制 zorder?
- google-apps-script - 使用应用程序脚本更新嵌入式图表会破坏垂直轴格式
- python - 如何在 AWS CDK 中复制和修改密钥
- c++ - 在 VS Code 中构建 wxWidgets 项目
- javascript - 如何在 Redux 中更新状态 - 上下移动 todo - React
- reactjs - 当我运行 npm test 时,xstate 不会改变我机器的状态(如果我运行应用程序,它会正常工作)
- javascript - 如何访问“我们的世界”数据 COVID-19 主疫苗 JSON 文件中的特定元素?
- redis - docker-compose 向redis添加数据
- java - File.mkdirs() 即使有权限也返回 false