【问题标题】:CanActivate returned true but still got 401 Unauthorize error in componentCanActivate 返回 true 但组件中仍然出现 401 Unauthorized 错误
【发布时间】:2020-10-17 03:09:30
【问题描述】:

CanActivate 确实返回了 true,但在我调用数据库时在我的组件中仍然出现 401 错误。

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private route: ActivateRouteSnapshot, private tokenService: TokenService) {}

  public canActivate = (
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean => {
    const token = this.tokenService.token; // get jwt token 
    if (!token || this.isTokenExpired(token)) {
        this.route.navigateByUrl('/login');
        return false;
    }   
    return true;
  }
}

isTokenExpired 方法:

private isTokenExpired = (token: any): boolean => {
   return Number(token.issued_at) + Number(token.expires_in) >= new Date().getTime();
}

我设置了一个断点,发现它返回了 true。但是在我的组件中,我访问了数据库,但出现 401 错误。

我的组件

async ngOnInit() {
    await this.myService.getInformation('url').then(() => this.loading()).catch(this.showing = false;));}

另一个类中的getInformation 方法。

public getInformation = (url: string): Promise<void> => {
    return new Promise(resolve, reject) => {
       this.subscription.get().subscribe(response => {
            this.data = response;
            resolve();
       },
          error => {
              console.log(error); // 401 error here
              reject();
          });
    });
}

【问题讨论】:

    标签: angular jwt angular5


    【解决方案1】:

    根据您发布的内容,您缺少将身份验证令牌注入 Http 请求的 HttpInterceptor。

    good example:

    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
        constructor(public auth: AuthService) {}
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.auth.getToken()}`
      }
      });
       return next.handle(request);
     }
    }
    

    这将通过应用程序连接 Http 注入以将令牌插入到请求标头中。一旦它也至少被添加到 Angular 的 DI 提供程序中。

    然后使用它会自动像这样工作:

    // service method
    return this.http.get('myApi/mymethod');
    

    【讨论】:

    • 我在拦截器中有它。我怀疑return Number(token.issued_at) + Number(token.expires_in) &gt;= new Date().getTime(); 是错误的。也许我需要计时 1000。我的意思是 token.expires_in*1000。它应该使用少于New Date().getTime()
    • 你能展示一下你的HttpInterceptor实现吗?
    • 和你的差不多。我认为在 jwt token.expires_in 中以毫秒为单位。但是 token.issued_at 以秒为单位。我在文档中没有找到。但是,如果我乘以 1000,那么行为就是正确的。
    【解决方案2】:

    找到了。

    我将 apigee 用于我的 OAuthV2 政策。 this:

    issued_at 颁发访问令牌的日期以 Unix 纪元时间表示,以 毫秒 为单位。

    expires_in 访问令牌的过期时间。以 表示。虽然 ExpiresIn 元素以毫秒为单位设置过期时间,但在令牌响应和流变量中,该值以秒为单位表示。

    所以我在计算总和时必须匹配数据格式。

    private isTokenExpired = (token: any): boolean => {
        return Number(token.issued_at) + Number(token.expires_in*1000) < new Date().getTime();
    }
    

    这意味着

    Number(token.issued_at) + Number(token.expires_in)
    

    ==>

    Number(token.issued_at) + Number(token.expires_in*1000)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 2011-01-03
      • 1970-01-01
      相关资源
      最近更新 更多