【问题标题】:Angular 2 Router - CanActivate GuardAngular 2 路由器 - CanActivate Guard
【发布时间】:2020-12-25 15:54:29
【问题描述】:

如果用户的会话无效,我正在实现 CanActivate 保护以将用户重定向到登录页面。

关于会话是否有效的检查是通过服务完成的,因此我订阅了服务调用以获取会话有效性状态。

我已经调试了代码,一切似乎都在正常工作,事实上,当会话无效时,应用程序会重定向回登录页面。但是,当我从守卫返回 true 时,页面没有加载。

我的代码类似于Angular documentation (Code on Plunker) 上列出的代码。

我不确定我是否在警卫本身中实施了错误。我可以看到的区别是守卫正在访问服务中的属性 - 但我认为这并不重要。据我所知,从守卫返回true 只会继续正常的路由操作。

注意:我使用的是 Angular RC3

代码:

守卫

export class MyGuard implements CanActivate {
    constructor(private checkSessionService: CheckSessionService, private router: Router) {}

    canActivate(
    next:  ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ) {
        this.checkSessionService.checkUserSession(localStorage.getItem('userToken'))
        .subscribe(validSessionReturn => {

            if (validSessionReturn) {
                return true;
            } else {
                // redirect to login
                this.router.navigateByUrl('/login');
                return false;
            }
        },
        error => console.log(error));
    }
}

编辑

我已经进一步调查,看起来我遇到的问题与我试图从订阅方法本身返回 boolean 的事实有关。作为测试,我尝试了以下方法,一切都按预期工作:

export class MyGuard implements CanActivate {
    constructor(private checkSessionService: CheckSessionService, private router: Router) {}

    canActivate(
    next:  ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ) {
        if(localStorage.getItem('userToken') !== null) {
            return true; // or return Observable.of(true);
        } else {
            return false; // or return Observable.of(false);
        }
    }
}

您可以从上面的代码中注意到,可以返回booleanObservable<boolean>。我实现的CheckSessionService 确实返回了Observable<boolean>。事实上,当我尝试下面的代码时,一切都再次按预期工作,这意味着如果会话有效,则页面加载成功,否则路由停止:

export class MyGuard implements CanActivate {
    constructor(private checkSessionService: CheckSessionService, private router: Router) {}

    canActivate(
    next:  ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ) {
        return this.checkSessionService.checkUserSession(localStorage.getItem('userToken'));
    }
}

但是,在上面的示例中,我找不到根据服务检索到的值重定向到特定页面的方法。我现在的问题是是否有一种方法可以在没有订阅方法的情况下检查this.checkSessionService.checkUserSession(localStorage.getItem('userToken')) 的结果,或者有一种不同的方法可以从subscribe 方法返回。我确实尝试过:

if(this.checkSessionService.checkUserSession(localStorage.getItem('userToken')) === Observable.of(false))

但正如预期的那样,它不起作用。

【问题讨论】:

    标签: angular angular-routing


    【解决方案1】:

    替换

    this.checkSessionService...
    

    return this.checkSessionService...
    

    除了订阅 observable 并返回 subscrtion,您还必须返回 observable 本身,但插入一些东西以防它为 false:

    return this.checkSessionService.checkUserSession(localStorage.getItem('userToken'))
        .do(‌​function(authenticated) { 
            if (!authenticated) ... 
        });
    

    【讨论】:

    • 我之前确实尝试过。但是,使用我拥有的代码执行此操作将返回 Subscription 而不是 booleanObservable<boolean> 这是不允许的。我确定我的代码没问题,只是在返回true 时,它就像我在返回false 并停止路由操作。
    • 您的回复似乎为我指明了正确的方向,但我有一个小问题,我已根据我的发现更新了问题。
    • 是的,我回答得太快了,并且混淆了 Observables 的承诺。基本上,您需要返回一个 Observable,这是您的服务返回的内容,但如果布尔值为 false,您还必须执行一些操作。这就是do 运算符允许做的事情。 reactivex.io/documentation/operators/do.html。 `return this.checkSessionService.checkUserSession(localStorage.getItem('userToken')).do(function(authenticated) { if (!authenticated) ... });
    • 完美!刚刚更新了我的代码,一切都好!我确实需要更多地了解 Observables :) 到目前为止,我使用的只是 subscribe 函数,并认为它也应该在这种情况下工作,但我错了。非常感谢你的帮助。 :)
    • 我也和他们一起受了很多苦:)
    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 2019-02-05
    • 2016-10-23
    • 2017-07-24
    • 2016-09-10
    • 2017-02-02
    相关资源
    最近更新 更多