Я использую Angular 7.
Я новичок в Angular, и в агентстве, где я работаю, мы собираемся создать новое угловое приложение.
Мой коллега создал бэкэнд(Restful), и я начал с функцией аутентификации.Итак, прежде всего у нас есть макет с верхней панелью и боковой панелью, они есть на каждом экране.
После того, как я сделал макет, я начал с компонента входа, я также создал JWT-перехватчик, чтобы добавить токенв любой заголовок.И создал AuthGuard для защиты большинства путей.
Я добавил AuthenticationService с функциями login, logout и isAuthenticated.
export class AuthenticationService {
public currentUserSubject: BehaviorSubject<User>;
public currentUser: Observable<User>;
returnUrl: string;
constructor(private http: HttpClient, private userService: UserService, private router: Router, private route: ActivatedRoute) {
if (localStorage.getItem("currentUser")) {
const userId = JSON.parse(localStorage.getItem("currentUser")).id;
userService.getById(userId).subscribe((data) => {
this.currentUserSubject = new BehaviorSubject<User>(data as User);
this.currentUser = this.currentUserSubject.asObservable();
});
}
}
isAuthenticated() {
const authState = new Subject<boolean>();
this.currentUser.subscribe(data => {
console.log(data);
if (data) {
authState.next(true);
} else {
authState.next(false);
}
});
return authState.asObservable();
}
login(email: string, password: string) {
return this.http.post<any>(`http://pitchbook.localhost/authentication_token`, {
username: email,
password
})
.pipe(map(object => {
// login successful if there's a jwt token in the response
if (object.user && object.token) {
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
const jsonObject = {
id: object.user.id,
token: object.token
};
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(jsonObject));
return jsonObject;
}
return object;
}));
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
this.currentUserSubject.next(null);
location.reload(true);
}
}
И затем я вызвал login () в форме SubmitLoginComponent.
onSubmit() {
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService.login(this.loginF.email.value, this.loginF.password.value)
.pipe(first()).subscribe(
(object) => {
this.userService.getById(object.id as number).subscribe((data) => {
this.authenticationService.currentUserSubject.next(data as User);
this.authenticationService.currentUser = this.authenticationService.currentUserSubject.asObservable();
console.log(this.authenticationService.currentUser);
this.router.navigate(["/dashboard"]);
this.alertService.success("Success");
});
},
(error) => {
this.loading = false;
this.alertService.error("Error");
}
);
}
Итак, проблема в том, что когда я вхожу в систему, получение пользователя с идентификатором занимает слишком много времени, и переход к «/ dashboard» происходит раньше.После этого AuthGuard пытается получить currentUser службы AuthenticationService, но его все еще нет, и поэтому я получаю ответный удар к «/ login» и должен снова войти в систему.После того, как меня выгнали "/ login", currentUser установлен в службе AuthGuard, но сейчас уже слишком поздно, и я не могу подписаться на него, потому что он не определен при первом вызове.
Я пытался получитьПользователь внутри канала в функции входа в систему AuthenticationService, но это не сработало.
В результате я ожидаю, что при нажатии кнопки входа в систему установлено значение currentUser (получить пользователя из API с идентификатором)(потому что объект пользователя довольно большой и не должен быть полностью в ответ на запрос аутентификации))
Я перехожу на / панель инструментов и в верхней панели я вижу свое имя пользователя.
Но вскрытый, AuthGuard должен следить, если пользователь прошел проверку подлинности, если нет, перейдите к /login.
После обновления страницы я хочу оставаться в системе
Надеюсь, вы, ребята, понимаете, о чем я, если не стесняйтесь спрашивать.Я могу добавить некоторые строки кода или при необходимости показать другие компоненты.