用于401的拦截器,续订和重试角度2

时间:2016-09-22 22:36:07

标签: angular jwt rxjs adal adal.js

ANGULAR 2 - RC5,ADAL.js

问题

所以我正在使用adal.js和angular 2进行Microsoft AD身份验证。我已经掌握了adal.js,可以登录,刷新令牌,注销,获取用户等等。

我现在的问题是处理扩展Http并创建一个自定义类,401上的将重试失败的请求

这基本上就是我现在所拥有的:

export class HttpInterceptor extends Http {
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router, private adal: IgAdal) {
       super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
       return this.intercept(super.request(url, this.getRequestOptionArgs(options)));
    } 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
       return this.intercept(super.get(url, this.getRequestOptionArgs(options)));
    }

    intercept(observable: Observable<Response>): Observable<Response> {
       return observable.catch((err, source) => {
         if (err.status  == 401) {   
            this.adal.acquireTokenObservable().flatMap(data=>{
                // NOT SURE WHAT TO DO HERE...
                return Observable.throw(err);
            })
         } else {
            return Observable.throw(err);
         }
      });
    }
}

当它不是401时,它会很好地抛出错误。现在,当我尝试在获取401并且获得新令牌之后调用super.get()...它不会再次尝试请求,而是我得到一个错误...

Cannot read property 'subscribe' of undefined

^^^我认为在返回所有请求后,这与订阅请求有关。

我认为值得指出的是,由于拦截器至少正在工作,因此我将main.ts设置得很好。

我的问题是:

  • 从拦截器内重试请求是否正确?或者稍后在订阅中重试订阅更有意义。
  • 重试请求是否是一种好习惯,还是最好通知用户再试一次? (我觉得这听起来不那么刺耳)
  • 是否有一个rxjs函数我可以用来在返回值后重试? (与“acquireToken”功能中的令牌一样)

编辑1

    intercept(observable: Observable<Response>): Observable<Response> {
    return observable.catch((err, source) => {
        if (err.status  == 401) {   
            return this.adal.acquireTokenObservable().flatMap(data=>{
               return observable.retry(3);
            })
        } else {
            return Observable.throw(err);
        }
    });
}

刚试过“重试”rxjs运算符..似乎正在做我想做的事情。现在我的问题是......在重试失败后如何将某人发送到登录页面?

这是我的第一个stackoverflow问题,所以如果它不是最好的布局我会道歉

谢谢!!

2 个答案:

答案 0 :(得分:0)

  1. 401未经授权,因此我们不会在拦截器中重试,请求被拒绝。如果您想重试,可以再次调用acquiretoken API。
  2. 让用户决定会更好。除非服务器关闭(http resopnses 500,503和504)或者如果网络超时并且您没有收到http响应。在这些情况下,开发人员端的重试将是首选。
  3. adal.js库中没有重试功能。如果要重试,则需要再次调用AcquireToken API。

答案 1 :(得分:0)

对于任何关注此事的人......我最终都会这样做。

intercept(observable: Observable<Response>): any {
    return observable.catch((err, source) => {
        if (err.status == 401) {
            return this.adal.acquireTokenObservable().flatMap(data=>{
                if (data === 'User login is required') {
                    this.adal.login();
                }
                return observable;
            })
        } else {
            return Observable.throw(err);
        }
    });
}

返回可观察流本身而不是.retry()似乎做了完全相同的事情,也只是重复1次。否则.retry(1)实际上会因某种原因抛出3个单独的错误。

  

this.adal.acquireTokenObservable()

我是否使用adal.js库来返回带有新令牌的流。仍在处理有关重试某些请求的其他几个问题,但这是一个良好的开端。