如何使用对话框截取未经授权的响应以输入密码并重试?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用对话框截取未经授权的响应以输入密码并重试?相关的知识,希望对你有一定的参考价值。
我正在构建一个应用程序,其后端具有简单的身份验证和GET
请求。我想向用户显示一个对话框,在其身份验证到期时重新输入密码。当您填写密码并单击“提交”时,我想重试原始HTTP调用并获取原始Observable
中的数据。我猜这是可能的,但我似乎无法找到一种方法开始。
这个问题类似:RxJS wait for second observable then retry original observable on error - TypeScript/Angular 2
但我正在使用.pipe()
和catchError
,所以我可以订阅我的API服务中的函数而不是单独的http调用。我不确定我应该提供哪些其他信息来清楚地表达我的问题,但如果您还需要了解其他信息,请告诉我。
这是我目前的代码:
import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { environment } from "../environments/environment";
import { Observable, ObservableInput } from "rxjs/Observable";
import { catchError, tap } from "rxjs/Operators";
import { MatDialog } from "@angular/material/dialog";
import { SessionExpiredComponent } from "./dialogs/session-expired/session-expired.component";
import "rxjs/add/observable/throw";
import { User } from "./classes/user";
import { Test } from "./classes/test";
const header = {
withCredentials: true
};
@Injectable()
export class ApiService {
user: User = null || JSON.parse(localStorage.getItem("user"));
constructor(private http: HttpClient, private matDialog: MatDialog) {}
private errorHandler() {
return (err: any) => {
let dialog = this.matDialog.open(SessionExpiredComponent, {
data: { err: err, email: this.user.email, apiService: this },
});
return dialog.afterClosed();
//I want to return a retry of the original observable
};
}
login(email: string, password: string): void {
const formHeader = {
headers: new HttpHeaders({
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
}),
withCredentials: true
};
this.http
.post<User>(
environment.backend + "auth/login",
"email=" +
encodeURIComponent(email) +
"&password=" +
encodeURIComponent(password),
formHeader
)
.subscribe(user => {
this.user = user;
localStorage.setItem("user", JSON.stringify(user));
});
}
getTests(): Observable<any> {
return this.http
.get<any>(
environment.backend +
"tests/query?accountId=" +
this.user.defaultAccount,
header
)
.pipe(catchError(this.errorHandler()));
}
}
此代码按原样运行,但在我输入密码并重新进行身份验证时不会重试该呼叫。
答案
我想到了。我可以通过使用Observable
将Observable
直接链接到另一个.flatMap()
之后。这意味着errorHandler
看起来像这样:
private errorHandler(source: Observable<any>) {
return (err: any) => {
let dialog = this.matDialog.open(SessionExpiredComponent, {
data: { err: err, email: this.user.email, apiService: this }
});
return dialog.afterClosed().flatMap(data => {
return source.retry();
});
};
}
关闭对话框后,它返回源Observable
的重试,我需要将其传递到errorHandler
,如下所示:
getTests(): Observable<any> {
let observable = this.http
.get<any>(
environment.backend +
"tests/query?accountId=" +
this.user.defaultAccount,
header
);
return observable.pipe(catchError(this.errorHandler(observable)));
}
现在我的getTests
函数是一个Observable,它将:
- 得到测试
- 如果失败,请显示密码对话框以重新连接
- 对话框完成后(这意味着我重新进行了身份验证),重试HTTP调用
以上是关于如何使用对话框截取未经授权的响应以输入密码并重试?的主要内容,如果未能解决你的问题,请参考以下文章
SQLSERVER使用密码加密备份文件以防止未经授权还原数据库