Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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 其中,刷新JWT令牌的角度请求生存期_Angular_Authentication_Jwt - Fatal编程技术网

Angular 其中,刷新JWT令牌的角度请求生存期

Angular 其中,刷新JWT令牌的角度请求生存期,angular,authentication,jwt,Angular,Authentication,Jwt,我还是一个棱角分明的新手。我想刷新一个访问令牌,但不确定在哪里刷新 我知道警卫和拦截器。在哪里做这件事最好?是否有我必须考虑的权衡 这里有许多问题说明了在这两种情况下如何做到这一点,但不要讨论“为什么”。我认为刷新应该发生在保护中,在请求周期的最开始,所以路由器知道是否要“激活”。但是,大多数示例在拦截器中显示它(通过查看到期时间,或者等待401然后刷新) 如有任何建议,将不胜感激 更新 我知道“如何”,我需要理解的是为什么。刷新的正确位置在哪里 警卫的工作是简单地检查用户是否登录,如果没有,

我还是一个棱角分明的新手。我想刷新一个访问令牌,但不确定在哪里刷新

我知道
警卫和
拦截器
。在哪里做这件事最好?是否有我必须考虑的权衡

这里有许多问题说明了在这两种情况下如何做到这一点,但不要讨论“为什么”。我认为刷新应该发生在保护中,在请求周期的最开始,所以路由器知道是否要“激活”。但是,大多数示例在拦截器中显示它(通过查看到期时间,或者等待401然后刷新)

如有任何建议,将不胜感激


更新
我知道“如何”,我需要理解的是为什么。刷新的正确位置在哪里

警卫的工作是简单地检查用户是否登录,如果没有,则重定向到登录页面

如果刷新令牌已过期,那么我认为对于
canActivate(ActivatedRouteSnapshot,RouterStateSnapshot)
,防护应该返回false,因为用户虽然经过身份验证,但不再具有当前授权


这就是为什么我倾向于把它放在门卫里。但大多数示例(包括下面的优秀示例)都显示了拦截器中的刷新。到那时,请求周期肯定已经很晚了?我在这里遗漏了什么?这仅仅是一个风格问题,还是角度请求周期中还有更多我应该考虑的问题?

您可以使用HttpInterceptor。因为每个API调用都通过拦截器,所以您可以检查令牌是否仍然有效,继续API调用

如果令牌过期,则显示toastr警报并阻止任何进一步的API调用

有关使用拦截器的更多信息,请访问此

完整代码:

http拦截器.service.ts

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { SessionService } from './session.service';
import { Router } from '@angular/router';
import { throwError } from 'rxjs';

declare var toastr;

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {

  constructor(private router: Router, private sessionService: SessionService) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    var token = this.sessionService.getToken();
    if (token != null && this.sessionService.isTokenExpired()) {
      this.sessionService.logOut()
      toastr.warning("Session Timed Out! Please Login");
      this.router.navigate(['/login'])
      return throwError("Session Timed Out")
    } else {

      const authRquest = req.clone({
        setHeaders: {
          Authorization: 'Bearer ' + token
        }
      })
      return next.handle(authRquest)
        .pipe(
          tap(event => {
          }, error => {
          })
        )
    }

  }
}
 providers: [
    {
        provide: HTTP_INTERCEPTORS,
        useClass: HttpInterceptorService,
        multi: true
      }
   ]
  getToken(): string {
    return localStorage.getItem('userToken');
  }

  getTokenExpirationDate(token: string): Date {
    token = this.getToken()
    const decoded = jwt_decode(token);

    if (decoded.exp === undefined) return null;

    const date = new Date(0);
    date.setUTCSeconds(decoded.exp);
    return date;
  }

  isTokenExpired(token?: string): boolean {
    if (!token) token = this.getToken();
    if (!token) return true;

    const date = this.getTokenExpirationDate(token);
    if (date === undefined) return false;
    return !(date.valueOf() > new Date().valueOf());
  }

  logOut(loginType?: string) {
    localStorage.removeItem('isLoggedin');
    localStorage.removeItem('userRole');

  }
会话服务.ts

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { SessionService } from './session.service';
import { Router } from '@angular/router';
import { throwError } from 'rxjs';

declare var toastr;

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {

  constructor(private router: Router, private sessionService: SessionService) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    var token = this.sessionService.getToken();
    if (token != null && this.sessionService.isTokenExpired()) {
      this.sessionService.logOut()
      toastr.warning("Session Timed Out! Please Login");
      this.router.navigate(['/login'])
      return throwError("Session Timed Out")
    } else {

      const authRquest = req.clone({
        setHeaders: {
          Authorization: 'Bearer ' + token
        }
      })
      return next.handle(authRquest)
        .pipe(
          tap(event => {
          }, error => {
          })
        )
    }

  }
}
 providers: [
    {
        provide: HTTP_INTERCEPTORS,
        useClass: HttpInterceptorService,
        multi: true
      }
   ]
  getToken(): string {
    return localStorage.getItem('userToken');
  }

  getTokenExpirationDate(token: string): Date {
    token = this.getToken()
    const decoded = jwt_decode(token);

    if (decoded.exp === undefined) return null;

    const date = new Date(0);
    date.setUTCSeconds(decoded.exp);
    return date;
  }

  isTokenExpired(token?: string): boolean {
    if (!token) token = this.getToken();
    if (!token) return true;

    const date = this.getTokenExpirationDate(token);
    if (date === undefined) return false;
    return !(date.valueOf() > new Date().valueOf());
  }

  logOut(loginType?: string) {
    localStorage.removeItem('isLoggedin');
    localStorage.removeItem('userRole');

  }

感谢这个非常好和非常完整的例子!然而,我想知道的是,像你所展示的那样,在拦截器中还是在警卫中这样做更好。虽然我不熟悉角度,但我的直觉告诉我,警卫是一个更好的位置,因为那是你决定是否激活路线的地方。但大多数例子都是这样的,我不确定这是不是风格问题,或者我的理解中缺少了什么…
Interceptor
就是这样做的地方。在
Guard
中,我们实际评估用户(登录用户)是否有权访问路由。而
Guard
是检查路由的地方,它与http调用无关,令牌与http调用相关,应该在
interceptors
ohhh中处理这些调用。。。现在我明白了。因此,警卫只需检查用户是否被允许访问该路由——他是否实际登录在该阶段无关紧要。谢谢你的澄清!:)老实说,我检查了你发布的链接,它证实了我的怀疑。我不确定警卫是不是最好的地方。它不执行某种ACL操作——它检查用户是否已登录,如果未登录,则重定向到登录页面。如果刷新令牌已过期,则
canActivate(路由:ActivatedRouteSnapshot,状态:RouterStateSnashot)
的答案应为false。我相信警卫是做这件事的地方,但我是个新手,所以我可能错了。谢谢。这是从活动项目复制的:)