登录后,调用scheduleRefresh()
函数,它将持续刷新令牌。刷新页面或经过身份验证的用户再次尝试访问网页时,会出现此问题。在启动时调用startupTokenRefresh
,令牌被刷新,但令牌永远不会像它的假设一样再次刷新。如果我在知道令牌过期后刷新页面,则会出现token_not_provided
错误,但我可以在网络控制台中看到令牌在此错误或页面加载后几秒钟刷新。如果我再次刷新,对我的api的请求就可以了,但令牌在过期后不再刷新。
我做错了什么?
app.component.ts(在应用启动时)
platform.ready().then(() => {
storage.ready().then(() => storage.get('token'))
.then(token => {
storage.set('token', token);
authService.token = token;
authService.authNotifier.next(true);
authService.checkToken();
authService.startupTokenRefresh();
});
authService.authenticationNotifier().subscribe((authed) => {
if (authed) {
this.rootPage = TabsPage;
} else {
authService.logout();
this.rootPage = LoginPage;
}
});
}
auth.service.ts
jwtHelper: JwtHelper = new JwtHelper();
token;
refreshSubscription: any;
authNotifier: ReplaySubject<boolean> = new ReplaySubject<boolean>(1);
authenticationNotifier(): Observable<boolean> {
return this.authNotifier;
}
refresh(): Observable<any> {
console.log("in refresh()");
let URL = `${myApi}/refresh?token=${this.token}`;
return this.authHttp.get(URL)
.map((rsp) => {
this.token = rsp.json().token;
this.storage.ready().then(() => this.storage.set('token', this.token));
this.authNotifier.next(true);
return rsp.json().token;
},
err => {
this.authNotifier.next(false);
this.logout();
console.log(err);
})
.share();
}
checkToken() {
if (this.token === '' || this.token === null || this.token === undefined) {
this.authNotifier.next(false);
this.logout();
}
}
public scheduleRefresh() {
if (this.token === '' || this.token === null || this.token === undefined) {
this.authNotifier.next(false);
this.logout();
}
else {
// If the user is authenticated, use the token stream provided by angular2-jwt and flatMap the token
let source = this.authHttp.tokenStream.flatMap(
token => {
let jwtIat = this.jwtHelper.decodeToken(this.token).iat;
let jwtExp = this.jwtHelper.decodeToken(this.token).exp;
let iat = new Date(0);
let exp = new Date(0);
let delay = (exp.setUTCSeconds(jwtExp) - iat.setUTCSeconds(jwtIat));
return Observable.interval(delay);
});
this.refreshSubscription = source.subscribe(() => {
this.refresh().subscribe((res) => console.log('-> Refreshed...'),
(error) => console.log('Refresh error: ' + JSON.stringify(error)))
});
}
}
public startupTokenRefresh() {
if (this.token === '' || this.token === null || this.token === undefined) {
this.authNotifier.next(false);
this.logout();
}
else {
// Get the expiry time to generate a delay in milliseconds
let now: number = new Date().valueOf() / 1000;
let jwtExp: number = this.jwtHelper.decodeToken(this.token).exp;
let iat: number = this.jwtHelper.decodeToken(this.token).iat;
let refreshTokenThreshold = 10; //seconds
let delay: number = jwtExp - now;
let totalLife: number = (jwtExp - iat);
(delay < refreshTokenThreshold ) ? delay = 1 : delay = delay - refreshTokenThreshold;
// Use the delay in a timer to // run the refresh at the proper time
return Observable.timer(delay * 1000);
});
// Once the delay time from above is reached, get a new JWT and schedule additional refreshes
source.subscribe(() => {
this.refresh().subscribe(
(res) => {
console.log('-> Refreshed on startup');
this.scheduleRefresh();
},
(error) => console.log('-> Refresh error:' + JSON.stringify(error)))
});
}
}
public unscheduleRefresh() {
console.log("unsched");
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
}
}
login.ts
onLogin() {
this.authService.login(this.loginForm.value.username, this.loginForm.value.password)
.subscribe(
(response) => {
this.storage.ready().then(() => this.storage.set('token', response.token));
this.authService.token = response.token;
this.authService.authNotifier.next(true);
},
error => {
console.log(error);
this.loginError = true;
this.authService.authNotifier.next(false);
},
() => {
console.log("login success");
this.authService.scheduleRefresh();
this.navCtrl.push(TabsPage);
},
);
}
}