Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 导航YURL似乎';不';不可能发生';在Safari上,如果拦截器在以前的请求中失败_Angular_Safari_Jwt_Interceptor - Fatal编程技术网

Angular 导航YURL似乎';不';不可能发生';在Safari上,如果拦截器在以前的请求中失败

Angular 导航YURL似乎';不';不可能发生';在Safari上,如果拦截器在以前的请求中失败,angular,safari,jwt,interceptor,Angular,Safari,Jwt,Interceptor,我有一个项目,其中设置了一个拦截器来刷新JWT令牌,如果http请求在其过期后发出,并且用户选择保持登录(与令牌本身一样存储在本地存储中) 此刷新过程的一部分包括一项检查,如果刷新失败或用户未选择保持登录,则该检查可以更改用户的登录状态(通过电子用户服务中的状态跟踪主题) Im在主应用程序组件中订阅了此状态更改,当它检测到用户已注销时,将(通过router.navigateByUrl)将用户导航到登录页面 这在除safari之外的所有浏览器上都能正常工作。我真的很难弄明白它为什么会失败。起初,我

我有一个项目,其中设置了一个拦截器来刷新JWT令牌,如果http请求在其过期后发出,并且用户选择保持登录(与令牌本身一样存储在本地存储中)

此刷新过程的一部分包括一项检查,如果刷新失败或用户未选择保持登录,则该检查可以更改用户的登录状态(通过电子用户服务中的状态跟踪主题)

Im在主应用程序组件中订阅了此状态更改,当它检测到用户已注销时,将(通过router.navigateByUrl)将用户导航到登录页面

这在除safari之外的所有浏览器上都能正常工作。我真的很难弄明白它为什么会失败。起初,我认为可能是因为我没有正确处理刷新异常而导致失败,但在显式捕获该错误之后,一个控制台日志语句演示了“navigateByUrl”调用实际上正在运行(通过将console.log语句放入调用的.then回调中)我完全搞不懂为什么浏览器没有更新

      // app.component catching the sign out to redirect user, note the 'Nav to the home page worked'
       this.userService.getSignInStateSubject().subscribe(state => {
            // if we were signed in and now we are not, redirect user immediately
            console.log('why has this not changed', state, this.signedInState);
            if (!state && this.signedInState) {
                // adding cleanup for log out here, rather than scatter it all over the place
                this.productService.setCurrentSelectedProduct(undefined);
                console.log('this needs to change immediately');
                this.routerService.navigateByUrl('/login').then(success => {
                    console.log('Nav to the home page worked');
                }, error => {
                    console.log(error);
                });
            }
            this.signedInState = state;
        });
\\用户服务“刷新”方法
公共attemptTokenRefresh():承诺{
返回新承诺((解决、拒绝)=>{
//console.log('我们在这里进行刷新'、localStorage.getItem(这个.STAY\u-SIGNED\u-IN\u-KEY)、Boolean(数字(localStorage.getItem(这个.STAY\u-SIGNED\u-IN\u-KEY))、localStorage.getItem(这个.refresh\u-TOKEN\u-KEY));
//如果用户选择不保持登录,则拒绝
if(!Boolean(数字(localStorage.getItem(this.STAY\u SIGNED\u IN\u KEY))){
这个.clearStoredData();
this.userSubject.next(未定义);
拒绝(“由于用户选择不保持登录,刷新失败”);
返回;
}
const refreshToken=localStorage.getItem(此.REFRESH\u令牌\u密钥);
//如果缺少或无效的刷新令牌,则拒绝
如果(!刷新令牌){
这个.clearStoredData();
this.userSubject.next(未定义);
拒绝('刷新失败,因为刷新令牌无效');
返回;
}
//尝试刷新
this.httpClient.post(environment.api_url+'/'+environment.refresh_令牌,JSON.stringify({refreshttoken}){
标题:新的HttpHeaders({
“内容类型”:“应用程序/json”
})
}).subscribe((authResult:{accessToken:string,refreshToken:string})=>{
//更新存储的令牌
setItem(this.ACCESS\u TOKEN\u密钥authResult.accessToken);
setItem(this.REFRESH\u TOKEN\u KEY,authResult.refreshToken);
const newTokenObject=this.parseAccessToken(authResult.accessToken);
//使用更新的令牌解析,以便在init函数或auth拦截器中使用
解析(authResult.accessToken);
},错误=>{
这个.clearStoredData();
this.userSubject.next(未定义);
拒绝(错误);
});
});
}
有人知道为什么这不起作用吗?(特别是在Safari vs chrome上,它似乎可以按预期工作时,不应该工作)

// auth interceptor
return next.handle(authReq).pipe(catchError(err => {
            // we need to make sure we dont try to refresh on authentication failure
            if ([400, 401].indexOf(err.status) > -1 && req.url !== environment.api_url + '/' + environment.tokens) {
                userService.redirectUrl = routingService.url;
                // convert to an observable and pipe the result
                return from(userService.attemptTokenRefresh()).pipe(
                    catchError(error => {
                        console.log('this caught the error and did nothing with it');
                        return of(error);
                    }),
                    switchMap(result => {
                        console.log('result', result);
                        if (result instanceof String) {
                            console.log('this got a real result');
                            authReq = req.clone({
                                setHeaders: { Authorization: 'Bearer ' + result }
                            });
                            return next.handle(authReq);
                        } else {
                            console.log('this has not worked well at all', result);
                            return EMPTY;
                        }
                    }),
                );
            } else {
                return throwError(err);
            }
        }));
\\ user service 'refresh' method
public attemptTokenRefresh(): Promise<string> {
        return new Promise((resolve, reject) => {
            // console.log('here we are doing the refresh', localStorage.getItem(this.STAY_SIGNED_IN_KEY), Boolean(Number(localStorage.getItem(this.STAY_SIGNED_IN_KEY))), localStorage.getItem(this.REFRESH_TOKEN_KEY));
            // reject if user chose not to stay signed in
            if (!Boolean(Number(localStorage.getItem(this.STAY_SIGNED_IN_KEY)))) {
                this.clearStoredData();
                this.userSubject.next(undefined);
                reject('Refresh failed as user chose not to stay signed in');
                return;
            }

            const refreshToken = localStorage.getItem(this.REFRESH_TOKEN_KEY);
            // reject if we have a missing or invalid refresh token
            if (!refreshToken) {
                this.clearStoredData();
                this.userSubject.next(undefined);
                reject('Refresh failed because of invalid refresh token');
                return;
            }

            // attempt a refresh
            this.httpClient.post(environment.api_url + '/' + environment.refresh_tokens, JSON.stringify({ refreshToken }), {
                headers: new HttpHeaders({
                    'Content-Type': 'application/json'
                })
            }).subscribe((authResult: { accessToken: string, refreshToken: string }) => {
                // update the stored tokens
                localStorage.setItem(this.ACCESS_TOKEN_KEY, authResult.accessToken);
                localStorage.setItem(this.REFRESH_TOKEN_KEY, authResult.refreshToken);
                const newTokenObject = this.parseAccessToken(authResult.accessToken);
                // resolve with the updated token for use ether in the init function or auth interceptor
                resolve(authResult.accessToken);
            }, error => {
                this.clearStoredData();
                this.userSubject.next(undefined);
                reject(error);
            });
        });
    }