我正在从事一个spring boot angular项目,其中用户从angular前端登录到spring boot上的身份验证api,该api返回一个JWT令牌。我还在Angular上设置了一个拦截器,该拦截器为所有请求附加带有JWT令牌的授权头。
我正在寻找一种拦截angualar请求的方法,这样当spring boot在JWT令牌过期后抛出401错误时,Angular前端将尝试使用过期的JWT和设置为true的新“isRefreshToken”头联系新的refreshtokenendpoint,以接收新的JWT。
这是我当前的AuthService
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private http: HttpClient) {}
login(username: string, password: string) {
return this.http
.post<iUser>('http://localhost:8080/authenticate', { username, password }).pipe(
tap(res => this.setSession(res)),
shareReplay()
)
}
refreshToken(){
return this.http.post<iUser>('http://localhost:8080/refreshtoken', {responseType: 'text' as 'json'}).pipe(
tap(res => this.setSession(res)),
shareReplay()
)
}
private setSession(authResult) {
let tokenInfo = this.getDecodedAccessToken(authResult.token);
const expiresAt = moment(tokenInfo.exp);
localStorage.setItem('id_token', authResult.token);
localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
localStorage.setItem('userId', tokenInfo.userId);
}
logout() {
localStorage.removeItem('id_token');
localStorage.removeItem('expires_at');
localStorage.removeItem('userId');
}
public isLoggedIn() {
return moment().isBefore(this.getExpiration());
}
isLoggedOut() {
return !this.isLoggedIn();
}
getExpiration() {
const expiration = localStorage.getItem('expires_at');
const expiresAt = JSON.parse(expiration);
return moment.unix(expiresAt);
}
getDecodedAccessToken(token: string): any {
try{
return jwt_decode(token);
}
catch(Error){
return null;
}
}
}
这是我正在使用的拦截器:
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private router: Router, private authService: AuthService){}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
let url = req.url.includes('localhost');
const idToken = localStorage.getItem('id_token');
if (idToken && url) {
const cloned = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + idToken),
});
console.log(cloned);
return next.handle(cloned);
} else {
return next.handle(req);
}
}
}
我可以向您建议另一种方法,我最近使用这种方法在令牌过期时注销用户。首先让我分享一下我的方法:
loginUser(email: string, password: string) {
const authData: AuthData = { email: email, password: password };
this.http.post<{ token: string, expiresIn: number }>('http://localhost:3000/api/users/login', authData).subscribe( response => {
const token = response.token;
this.token = token;
if(token) {
const expiresInDuration = response.expiresIn;
this.tokenTimer = setTimeout(() => {
this.logout();
}, expiresInDuration*1000);
this.isAuthenticated = true;
this.authStatusListener.next(true);
const now = new Date();
const expirationDate = new Date(now.getTime() + (expiresInDuration * 1000));
this.saveAuthData(token, expirationDate);
this.router.navigate(['']);
}
});
}
logout() {
this.token = null;
this.isAuthenticated = false;
this.authStatusListener.next(false);
clearTimeout(this.tokenTimer);
this.clearAuthData();
this.router.navigate(['']);
}
private saveAuthData(token: string, expirationDate: Date) {
localStorage.setItem('token', token);
localStorage.setItem('expirationDate', expirationDate.toISOString());
}
所以我在这里所做的是,我收到了一个expireIn
值,该值以令牌过期的秒为单位。然后我设置了一个timeout
回调方法,当达到该时间时将调用该方法。在这里,我已经注销了,在你的情况下,你可以调用刷新令牌的应用编程接口
在Interceptor/Guard中,令牌过期时没有额外的事情要做
要控制报头中的注销按钮,只需这样做:
userIsAuthenticated = false;
private authListenerSubs: Subscription;
constructor(private authService: AuthService) { }
onLogout() {
this.authService.logout();
}
ngOnInit() {
this.authListenerSubs = this.authService.getAuthStatusListener().subscribe(isAuthenticated => {
this.userIsAuthenticated = isAuthenticated;
});
}
ngOnDestroy() {
this.authListenerSubs.unsubscribe();
}
在超文本标记语言的ngIF
中使用userIsAuthentiated
。
对于一个真实的场景,你可以帮助这个github回购。
我需要(在拦截器类中)对403禁止的HTTP状态(获取/刷新)JWT令牌作出反应,并使用新令牌重试请求。 在下面的代码中,当服务器返回错误响应时,它将转到成功回调(而不是像我预期的那样进入错误回调),事件是typeof object(这在错误响应的反应中是无用的)。事件对象如下所示:{type:0}。 问题: -当我需要刷新accessToken并重试http请求时,如何在HttpIntercep
我已经实现了 JWT 和刷新令牌流。当我过去实现这一点时,我的做法略有不同,主要是刷新令牌是在正文中发送的。 但是现在我做了不同的事情,我必须通过授权标头发送访问令牌,但是我的拦截器代码不想切换不记名令牌。如何修复,如果我想刷新,我实际上使用刷新令牌作为不记名令牌,而不是过期的访问令牌? 我还尝试在post请求中将HTTP标头设置为授权承载令牌
我有一个使用express api的react应用程序。我正在尝试在访问令牌过期时刷新令牌。我正在使用axios拦截器来实现这一成就。 它卡在某个地方了。我使用console.log来调试它。从控制台; 发布http://localhost:5000/api/auth/token?null 401(未经授权) 之后什么都没发生。我该怎么办?谢谢你的帮助
我有 401 拦截器,当access_token过期时,有一个请求的成功案例。拦截器重新加载令牌并返回 next.handle(customReq)。但是当同时发出 2 个或更多请求并且两个请求的令牌都已过期时,我遇到了问题,因为第二个请求尝试再次刷新,但现在刷新令牌无效。所以。。。。我尝试设置一个标志只执行一次,并使用自定义可观察量返回。问题是组件现在永远不会成功,我无法删除加载器。 HTTP
问题内容: 我有一个有角度的应用程序,有时每个状态会执行多个$ http.get请求。该应用将JWT用于带有刷新令牌的用户身份验证。API服务器会发送由于身份验证错误而失败的每个请求。我做了一个请求,该请求在401错误时请求带有刷新令牌的新令牌,然后重新发送原始请求。 问题是,如果一个状态发出例如2个$ http.get请求,并且都获得401响应,那么我将访问令牌更新两次。显然,我只想刷新一次令牌