Angular 8 .next似乎无法正常工作

时间:2019-08-21 17:03:47

标签: angular auth-guard

我正在尝试创建一个对用户进行身份验证并将令牌存储在localStorage中的服务。 我希望其他服务(特别是auth Guard)能够访问当前用户,因此我已经设置了身份验证服务的构造函数,如下所示:

currentUserSubject: BehaviorSubject<Token>;

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}

当用户使用http POST请求登录时,如果成功,则在next上调用currentSubject方法,如下所示:

return this.http.post<Token>(`${environment.identityServerUrl}/connect/token`, params, httpOptions)
    .pipe(map(user => {
        localStorage.setItem('currentUser', JSON.stringify(user));
        console.log(user);
        this.currentUserSubject.next(user);
    }));

问题是,它似乎不起作用。如果我检查我的身份验证防护,它只会将用户视为空。仅在刷新时才填充(由于身份验证服务构造函数)。

我的身份验证防护看起来像这样:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { mapTo, take, filter } from 'rxjs/operators';

import { AuthenticationService } from './authentication.service';

@Injectable({ providedIn: 'root' })
export class AuthGuardService implements CanActivate {
    constructor(
        private router: Router,
        private authenticationService: AuthenticationService
    ) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
        return this.authenticationService.currentUserSubject.pipe(
            filter(user => !!user), 
            mapTo(true),
            take(1)
        );
    }
}

有人知道我在做什么错吗?


如果我将canActivate方法更改为此:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean|UrlTree {
    var user = this.authenticationService.currentUserSubject.value;
    console.log(user);

    if (user) return true;

    this.router.navigate(["login"],{ queryParams: { retUrl: route.url} });
    return false;
}

它应该可以工作,但是只是控制台日志显示null,所以它只停留在登录页面上。

我看到您可以从本文中获得.valuehttps://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

1 个答案:

答案 0 :(得分:0)

主题next()方法用于将消息发送到可观察对象,然后将消息发送到订阅该可观察对象的角度组件。

您仅创建了一个主题,但尚未创建守卫可以订阅的观察对象。

currentUserSubject: BehaviorSubject<Token>;
currentUser$ = this.currentUserSubject.asObservable();

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}

按照惯例,可观察对象的末尾带有$符号。现在我们已经创建了一个可观察对象,可以接收您主题的消息,我们可以在守护程序中订阅它。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.authenticationService.currentUser$.subscribe(user => {
        console.log(user);
    });
}

我也不确定您为什么使用filter,使用map就足够了。