当前位置: 首页 > 知识库问答 >
问题:

返回令牌之前的AcquireToken可观察错误

东郭鹤龄
2023-03-14

我正在使用adal-angular4库在angular 4单页应用程序中进行隐式流实现。这个应用程序调用一个web api来显示结果。这两个应用程序都托管在azure中(在一个特定的租户中),并进行了适当的注册,配置工作正常。

1. AuthenticationGuard.ts 

从“@Angular/Core”导入{Injectable}; 从'rxjs/Observable'导入{Observable}; 从“@Angular/Router”导入{Router,CanActivate,CanActivateChild,ActivatedRouteSnapshot,RouterStateSnapshot,NavigationExtras}; 从“ADAL-Angular4”导入{AdalService};

@injectable() 导出类AuthenticationGuard实现CanActivate、CanActivateChild{

constructor(
    private router: Router,
    private adalSvc: AdalService
) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.adalSvc.userInfo.authenticated) {
        return true;
    } else {
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return false;
    }
}

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    return this.canActivate(childRoute, state);
}}

AppComponent.ts

@component({selector:'app-root',templateurl:'./app.component.html',styleurls:['./app.component.css']})导出类AppComponent实现OnInit{title='My Portal‘;isLoggedIn=false;LoggedInUser:String;private BodyTag:Any;构造函数(private AdalService:AdalService,private Router:Router){This.AdalService.Init(Environment.AzureConfig);This.BodyTag

ngOnInit(){console.log(“AppComponent Init”);This.AdalService.HandleWindowCallback();if(This.AdalService.UserInfo.Authenticated){This.IsLoggedIn=This.AdalService.UserInfo.Authenticated;This.LoggedInUser=This.AdalService.UserInfo.Profile.Name;}Document.AddEventListener(“KeyDown”,()=>This.HandleEvt);}

logout():void{this.adalService.logout();}}

LoginComponent.ts

从“@Angular/Core”导入{Component,OnInit,Injectable,Inject};从“@Angular/Router”导入{ActivatedRoute,Router};从“ADAL-Angular4”导入{AdalService};从“../app.constants”导入{APP_CONFIG,AppConfig};

@component({selector:“app-login”,templateurl:“./login.component.html”,styleurls:[“./login.component.css”]})导出类LoginComponent实现OnInit{

isLoggedIn=false;LoggedInUser:字符串;LocallogGedInUser:any;TokenNew:字符串;

构造函数(private Route:ActivatedRoute,private Router:Router,private AdalService:AdalService,@Inject(APP_CONFIG)private AppConfig:AppConfig){}

ngOnInit(){This.AdalService.HandleWindowCallback();if(This.AdalService.UserInfo.Authenticated){This.IsLoggedIn=This.AdalService.UserInfo.Authenticated;This.LoggedInUser=This.AdalService.UserInfo.Profile.Name;}}

login():void{const returnUrl=this.route.snapshot.queryparams[“return url”]“/”;if(this.adalservice.userinfo.authenticated){this.router.navigate([returnUrl]);}else{this.adalservice.login();}}}

ts(负责通过getAll()方法进行第一个API调用。

从“@Angular/Core”导入{Injectable,OnInit,Inject};从“@Angular/Http”导入{Headers,Http,Response,RequestOptions};从“@Angular/common/http”导入{HttpClient,HttpHeaders};从'rxjs/Observable'导入{Observable};导入“../rxjs-extensions”;从“../app.constants”导入{APP_CONFIG,AppConfig};@injectable()导出类ProductService实现OnInit{headers:Headers;TokenNew:String;Items:Products[];LoggedInUserName:String;LoggedInUserEmail:String;baseUrl=“https://MyProductsAPI/”;productListEndpoint=This.baseUrl+“/Products”;构造函数(私有Http:HttpClient,私有HttpBase:Http,@inject(APP_CONFIG)私有AppConfig:AppConfig,私有AdalService:AdalService)

public getAllProducts():observable>{return this.httpbase.get(this.ProductListEndpoint,this.getRequestOptionsWithHeadersForHTTP()).map(response=>{const tmp=response.json();return tmp;});}

私有getRequestOptionsWithHeadersForHTTP():RequestOptions{ This.ActemtacQuireToken(); This.TokenNew=This.AdalService.GetCachedToken(This.AppConfig.ResourceApplicationID); const headersNew=新标头({“content-type”:“application/json”}); HeadersNew.Append('Authorization','Bearer'+This.TokenNew); const options=new RequestOptions(); Options.Headers=HeadersNew;

在调用API之前,我如何确保令牌存在-就目前情况而言,为检索product list而进行的方法调用的顺序如下所示

>

  • 调用getAllProducts()--这是负责调用API的主要方法。这将启动对其他方法的嵌套调用。

    getAllProducts()调用getRequestOptionsWithHeadersForHTTP()以获取与http请求相关联的RequestOptions(头),然后将请求触发到apiendpoint。

    getRequestOptionsWithHeadersForHTTP()调用AttpacQuireToken()从adal服务获取令牌。

    尝试acquiretoken()调用acquiretoken()-该方法首先检查是否存在缓存的令牌,如果没有,则调用acquiretoken来检索一个。在这里,调用直接执行“error”lambda中的代码块,从而在UI中引发错误。几秒钟后,当acquiretoken重新创建令牌时,它执行“token”lambda中的代码。

    这只在用户第一次登录并且缓存中没有令牌时发生。对于后续的尝试,这工作很好(检索缓存的令牌)。

  • 共有1个答案

    单嘉泽
    2023-03-14

    您可以像这样使用Promise或chain observable:

    private attemptAcquireToken():Observable<boolean> {
        this.tokenNew = this.adalService.getCachedToken(this.appConfig.resourceApplicationId);
        console.log('1. token from attemptacquiretoken ' + this.tokenNew);
        // this.tokenNew = null;
        if (this.tokenNew == null) {
            console.log('2. token new is null - trying to acquiretoken using adal');
            this.adalService.acquireToken(this.appConfig.resourceApplicationId).subscribe(
              token => {
                ...
                return Observable.of(true);
              }, // never comes
              error => {
                ....
                return Observable.of(false);
        }  
    }
    
    private getRequestOptionsWithHeadersForHTTP(): Observable<RequestOptions> {
        this.attemptAcquireToken().subsribe(r => {
        if (r !== false) {
                ...
                options.headers = headersNew;
                return Observable.of(options);
            } else {
                return Observable.of(undefined);
            }
        });
    }
    

    等等...

     类似资料:
    • 函数应该从get请求返回一个 在这种情况下,我只能在为真时执行请求,否则我在函数

    • 有人能向我解释一下为什么运算符可以接受返回或的函数吗? 官方文件说: FlatMap运算符通过将您指定的函数应用于源可观察对象发出的每个项目来转换可观察对象,其中该函数返回本身发出项目的可观察对象。 为什么它也可以返回数组? 例如,它们都是有效的: 但这不起作用:

    • 我对Observables和RxJs是新手,我想对回报进行调整。如果第一个选择器返回某个值,我希望第二个选择器可以观察到。但是如果第一个选择器没有返回那个特定的值,我想返回false,而不是(false)。我已经走了这么远,但这返回了一个可观察的结果

    • 我正在为我的全堆栈应用程序构建一个angular2前端。我正在进行用户登录,我有这个功能,当提交登录表单时调用: 我的userService中的登录功能如下: 最后,handleError函数: 当我提交错误的密码时,我会收到错误信息: 401-未经授权的响应,状态为:401未经授权的URL:http://localhost:3000/api/login 从我的错误处理程序中的变量打印。这很好,但

    • 问题内容: 我一直在阅读Observer模式,以保持UI处于最新状态,但仍然看不到它的用途。即使在我的特定对象中通知了我的MainActivity然后运行update();方法我仍然无法使用Pet对象来获取更新值,因为该对象是在Oncreate中创建的…而我只是无法创建新对象,因为那时变量会有所不同..这是我的实施,它似乎不起作用。 观察者/ MainActivity 可观察/宠物 问题答案: 首

    • 我有一个组件订阅服务中的一个可观察对象。该方法反过来订阅另一个服务中的可观察对象。我想将一个数组从最后一个服务传递回第一个服务,然后第一个服务将该数组传递回组件。更具体地说,该组件调用其本地服务,然后调用一个数据服务,该数据服务通过http客户端访问我的数据库。http客户端正在工作,数据服务将数组返回给本地服务。本地服务接收数组,但我不知道如何将该数组作为可观察对象传递回组件。以下是简短的代码块