Angular 角度4:可观察不工作

Angular 角度4:可观察不工作,angular,observable,Angular,Observable,我正在使用的应用程序通过Angular 2+的adal.js端口实现Azure Active Directory授权,该端口工作得非常好 我们有一个AuthenticationGuard,它处理对我们自己的AdalService的调用。AdalService有一个功能ensureAuthenticatedAsync,用于检查用户是否已登录,如果未登录,则将其重定向到广告登录页面 我们现在有了新的要求,当没有可用的AD帐户时,可以使用自定义生成的令牌进行替代登录。经过一些修改后,我的代码如下所示:

我正在使用的应用程序通过Angular 2+的adal.js端口实现Azure Active Directory授权,该端口工作得非常好

我们有一个
AuthenticationGuard
,它处理对我们自己的
AdalService
的调用。
AdalService
有一个功能
ensureAuthenticatedAsync
,用于检查用户是否已登录,如果未登录,则将其重定向到广告登录页面

我们现在有了新的要求,当没有可用的AD帐户时,可以使用自定义生成的令牌进行替代登录。经过一些修改后,我的代码如下所示:

身份验证.guard.ts

public-canActivate(路由:ActivatedRouteSnapshot,状态路由StateSnashot):布尔值{
...
设params=route.queryParams;
let token=(params!==null&¶ms['token']!==未定义)?params['token']:null;
this.adalService.ensureAuthenticatedAsync(令牌);
...
返回true;
}
adal.service.ts

私有上下文:adal.AuthenticationContext;
public-ensureAuthenticatedAsync(令牌:字符串| null=null){
log('ensureAuthenticatedAsync',令牌);
this.isAuthenticated.subscribe(isAuthenticated=>{
如果(!已验证){
console.log('未经过身份验证);
如果(令牌===null){
//转发至AAD登录页面->此操作非常有效
this.context.login();
}否则{
...
log('accessToken before',this.accessToken);
this.customToken=令牌;
log('accessToken后面的'this.accessToken');
...
}
}
});
}
public get accessToken():字符串{
log('get accessToken'中的customToken',this.customToken);
return(this.customToken==null)?this.context.getCachedToken(this.adalClientId):this.customToken;
}
public get isAuthenticated():可观察{
log('get isAuthenticated'中的accessToken',this.accessToken);
让isAuthenticated:boolean=(this.accessToken!==null);
可观察的返回(未验证);
}
应用程序组件.ts

public ngOnInit():void{
this.adalService.isAuthenticated.subscribe(isAuthenticated=>{
如果(未经验证){
//在这里做些事情
}
});
}
应用程序路由.ts

导出常量路由:路由=[
{路径:'Dashboard',组件:DashboardComponent,canActivate:[AuthenticationGuard]},
{路径:“拒绝访问”,组件:AccessDeniedComponent}
];
这是控制台中记录的内容:

authentication guard  
customToken in get accessToken null  
accessToken in get isAuthenticated null  
customToken in get accessToken null  
ensureAuthenticatedAsync 12345  
not authenticated  
customToken in get accessToken null  
accessToken before null  
customToken in get accessToken 12345  
accessToken after 12345  
customToken in get accessToken 12345
定期访问页面()会正确地触发重定向到AD登录页面,然后在登录后返回到我的应用程序。在那里,缓存的AD令牌会被更改,并且无论订阅到哪里,都会触发ISAuthentication(在我的例子中是
app.component.ts

但是,使用令牌()访问页面不起作用。即使使用参数中的值修改了
customToken
,更改似乎不会传播,并且在订阅中保持
false

我错过什么了吗?

试试:

在您的日常服务.ts中:

import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
...
public get isAuthenticated(): Observable<boolean> {
 let isAuthenticated: boolean = (this.accessToken !== null);
 return of(isAuthenticated);
}
从'rxjs/Observable'导入{Observable};
从“rxjs/observable/of”导入{of};
...
public get isAuthenticated():可观察{
让isAuthenticated:boolean=(this.accessToken!==null);
归还(未经认证);
}

我认为问题在于防护本地化

你的警卫在/仪表板路线上。因此,如果只加载AuthenticationGuard,则不会调用它,从而确保也不会调用AuthenticatedAsync。因此,在adal.service.ts中没有customToken的重定向和更新

如果要在appComponent中使用guard的计算结果,则必须在“引导”到appComponent的路由上使用guard

编辑: 问题是你误解了反应性行为。isAuthenticated的实现方式是,它将发出一次布尔值,然后完成。因此,您在app.component中的订阅将只触发一次


您正在寻找的是行为主题,在需要或customToken更改时,您可以在其中“推送”新数据。

您可以添加app.component.ts的相关代码和customToken如何修改的示例吗?顺便说一句,isAuthenticated返回一个observable似乎很奇怪,因为其中没有异步任务。我已经从app.component.ts中添加了代码,我在那里订阅了属性。customToken在adal.service.ts(this.customToken=token)中被修改。至于可观察的:在那之前我有一个简单的布尔属性,当从adal登录返回时它没有刷新值。我尝试了一个observable,它成功了。你能添加你的路由配置和一个带有自定义令牌的路由示例,以了解如何调用身份验证卫士吗?我在app.routes.ts中添加了两个条目的示例,一个有身份验证卫士,另一个没有身份验证卫士。另外,我最后更改了描述,添加了更多细节,包括路线示例。您介意解释一下这会有什么不同吗?与(isAuthenticated)的返回(isAuthenticated)不同的是,
返回(isAuthenticated)
?单独使用rxjs库使得只使用必要的内容优化产品构建成为可能。我们需要更多信息来调试此脚本。这是一个误解,实际上,任何不匹配的路由都会重定向到/Dashboard。我在问题中的代码中添加了一些console.logs,以向您展示我尝试了什么以及它实际输出了什么。您可以看到它实际上已更新,但未触发isAuthorized,并且app.component.ts中的订阅不知道