Angular: 在拦截器中添加不记名令牌
Angular: Adding bearer token in interceptor
我正在使用 Angular + AWS Cognito
我能够登录并需要添加 Cognito 持有者令牌
@Injectable({
providedIn: 'root',
})
export class InterceptorService implements HttpInterceptor {
constructor(public loaderService: LoaderService, private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
getToken() {
return from(
new Promise((resolve, reject) => {
Auth.currentSession().then((session) => {
if (!session.isValid()) {
resolve(null);
} else {
resolve(session.getIdToken().getJwtToken());
}
}).catch(err => { return resolve(null) });
})
);
}
}
这段代码工作正常,问题是这里如何处理HttpResponse?
我尝试了以下代码,但没有成功,请求没有 Bearer token
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(
(event) => {
if (event instanceof HttpResponse) {
if (event.status !== 200) {
console.log('Response', event.status);
}
} else {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
},
(error) => {
// to handle errors
}
)
}
据我所知tap
只有运行s,当时没有报错。如果你想让你的函数在出错时运行,你必须在管道中使用catchError()
。
tap 是产生副作用的运算符,你不能 return 从回调中观察到它,它不会被订阅。发送原始请求并在失败时使用令牌重试的逻辑也有点奇怪。我相信你应该为每个请求添加令牌。
intercept(...) {
return this.sendWithToken(request).pipe(
catchError(error => error.status === 401 ? this.sendWithToken(request) : throwError(error)) // try one more time if return code is 401
);
}
sendWithToken(request: ...) {
return this.getToken().pipe(
mergeMap(token => addToken(request)),
mergeMap(authedRequest => next.handle(authedRequest)),
);
}
还可以改进 getToken 代码,因为如果您已经有一个,则不需要创建 promise
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null);
);
}
我用以下拦截器代码解决了这个问题:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
headers: request.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(request).pipe(
tap(evt => {
// modify here
}),
catchError((error: any) => {
if (error && error.status) {
if (error.status == 401) {
this.router.navigate(['/']);
}
} else {
return throwError(error);
}
})
)
})
);
}
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null)
);
}
我正在使用 Angular + AWS Cognito
我能够登录并需要添加 Cognito 持有者令牌
@Injectable({
providedIn: 'root',
})
export class InterceptorService implements HttpInterceptor {
constructor(public loaderService: LoaderService, private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
getToken() {
return from(
new Promise((resolve, reject) => {
Auth.currentSession().then((session) => {
if (!session.isValid()) {
resolve(null);
} else {
resolve(session.getIdToken().getJwtToken());
}
}).catch(err => { return resolve(null) });
})
);
}
}
这段代码工作正常,问题是这里如何处理HttpResponse?
我尝试了以下代码,但没有成功,请求没有 Bearer token
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(
(event) => {
if (event instanceof HttpResponse) {
if (event.status !== 200) {
console.log('Response', event.status);
}
} else {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
},
(error) => {
// to handle errors
}
)
}
据我所知tap
只有运行s,当时没有报错。如果你想让你的函数在出错时运行,你必须在管道中使用catchError()
。
tap 是产生副作用的运算符,你不能 return 从回调中观察到它,它不会被订阅。发送原始请求并在失败时使用令牌重试的逻辑也有点奇怪。我相信你应该为每个请求添加令牌。
intercept(...) {
return this.sendWithToken(request).pipe(
catchError(error => error.status === 401 ? this.sendWithToken(request) : throwError(error)) // try one more time if return code is 401
);
}
sendWithToken(request: ...) {
return this.getToken().pipe(
mergeMap(token => addToken(request)),
mergeMap(authedRequest => next.handle(authedRequest)),
);
}
还可以改进 getToken 代码,因为如果您已经有一个,则不需要创建 promise
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null);
);
}
我用以下拦截器代码解决了这个问题:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
headers: request.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(request).pipe(
tap(evt => {
// modify here
}),
catchError((error: any) => {
if (error && error.status) {
if (error.status == 401) {
this.router.navigate(['/']);
}
} else {
return throwError(error);
}
})
)
})
);
}
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null)
);
}