【问题标题】:Handling multiple ajax http requests using Observables使用 Observables 处理多个 ajax http 请求
【发布时间】:2016-12-02 20:26:19
【问题描述】:

我有一个 angular2 网站,它在启动时使用 Json Web Tokens 发送多个 ajax 请求以进行授权

他们是这样的:

public getUser(): Observable<User> {
    let headers = new Headers({
        'Authorization': 'Bearer ' + this.authService.token.access_token,
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });
    let options = new RequestOptions({ headers: headers });
    return this.http.get('http://localhost:5000/api/users/profile', options)
        .map(response => response.json() as User).catch(this.handleError);
}


public getFriends(): Observable<User[]> {
    let headers = new Headers({
        'Authorization': 'Bearer ' + this.authService.token.access_token,
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });
    let options = new RequestOptions({ headers: headers });
    return this.http.get(`http://localhost:5000/api/users/${this.authService.userId}/friends`, options)
        .map(response => response.json() as User[]).catch(this.handleError);
}

等等

但我需要访问令牌来执行此请求 我将它存储并在本地存储中刷新令牌,但访问令牌在 5 分钟后过期

所以当用户登录时访问和刷新令牌存储在本地存储中

如果用户在登录后关闭浏览器,等待 5 分钟或更长时间,然后再次打开页面,我们需要刷新它(使用另一个请求)然后发送我们的请求

这里是主要问题:我们不知道将发送多少或什么请求,所以我们不能硬编码它

这里是更新请求

 public update(): Observable<boolean> {
        let headers = new Headers({
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        });


        let options = new RequestOptions({ headers: headers });
        return  this.http.post('http://localhost:5000/api/auth/token', "refresh_token=" + encodeURIComponent(this.token.refresh_token) + "&grant_type=refresh_token", options)
            .map((response: Response) => {

                let token = response.json();
                if (token) {
                    this.token = token;
                    localStorage.setItem('currentUser', JSON.stringify({
                        token: this.token,
                        userId: this.userId
                    }));
                    return true;
                }
                else {
                    return false;
                }
            }).catch(this.handleError);  

}

如果做这样的事情:

this.authService.update().flatMap(this.getUser);

这无济于事,因为我们会发送大量“更新”请求,这对我们没有任何好处

仅发送“更新”请求也无济于事,因为我们将发送一个“更新”和许多其他请求

那么解决这个问题的方法是什么?

【问题讨论】:

  • 让我看看我是否做对了。您要确保: a) 您不会向服务器发送大量“更新”请求; b) 自上次更新后 5 分钟后,当您拨打任何其他电话时,您仍然需要拨打更新电话。我没听错吗?
  • @AlexanderLeonov 是的

标签: ajax angular typescript rxjs


【解决方案1】:

将访问令牌存储在本地存储中被认为是不安全的。任何本地脚本都可以访问它。

因此,虽然不是您要求的,但我建议您使用仅限 http 的 cookie。 Cookie 有一个设置的过期时间,因此这将有助于您的要求。

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

这个 cookie 是通过 HTTPXMLRequest(angular/http 底层访问)自动发送的。

然后每当请求因令牌过期而失败时,您可以捕获,生成另一个令牌,然后重试:

http.get(...)
    .catch(obs => {
       return refreshToken().mergeMapTo(obs);
    })

因为是http-only,没有脚本可以访问,所以失败后需要重做,也就是可以提前想好。

【讨论】:

  • 我不能使用cookies进行授权,服务器需要授权标头,这也不能解决许多请求同时失败的问题,因为所有失败的请求都会发送更新请求
猜你喜欢
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
  • 2016-03-29
  • 2017-08-10
相关资源
最近更新 更多