页面加载前如何处理令牌?

时间:2019-11-10 11:11:01

标签: node.js angular jwt

我使用JWT进行身份验证(没有登录页面)。 我有一个问题,当站点加载时,首先启动的是获取方法,用于加载内容,然后是身份验证方法,然后将令牌保存在本地存储中。

问题是我收到未通过身份验证的错误,并且刷新页面后仍无法正常工作。 我需要让他先制定身份验证方法,然后将他保存到本地存储中,然后再加载页面。

身份验证服务:

import { Injectable } from '@angular/core';
import { HttpService } from '../http/http.service';
import * as jwt_decode from 'jwt-decode';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  public isDialogOpen = false;

  constructor(private http: HttpService) { }

  authUser(userID) {
    if (localStorage.getItem('token') === null) {
      this.http.authUser(userID).subscribe((data) => {
        localStorage.setItem('token', data.token);
      }, error => {
        console.log(error);
      });
    }
  }

  removeToken() {
    localStorage.clear();
  }

  getCurrentUser() {
    try {
      const jwt = localStorage.getItem('token');
      return jwt_decode(jwt);
    } catch (error) {
      return null;
    }
  }
}

header.interceptor:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';

@Injectable()
export class HeaderInterceptor implements HttpInterceptor {
    constructor(public authService: AuthService) { }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const token = localStorage.token;
        if (!token) {
          return next.handle(request);
        }

        request = request.clone({
            setHeaders: {
                'Content-Type': 'application/json',
                'x-auth-token': token
            }
        });
        return next.handle(request);
    }
}

Error.interceptor.ts:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(public authService: AuthService) { }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(
            catchError(err => {
                if (err) {
                    console.log(`Server Error`);
                }
                if (err.status === 401) {
                    this.authService.authUser('1');
                }
                const error = err.error.message || err.statusText;
                return throwError(error);
            })
        );
    }
}

2 个答案:

答案 0 :(得分:0)

您应该将代码分开。您的请求处理不应明确地等待身份验证成功:相反,请在各处使用可观察对象。

Auth0 help page是一个很好的例子。即使您不使用Auth0后端,该体系结构也是适合的架构:您的auth服务将令牌返回为可观察的令牌,并在需要它的其他地方订阅该令牌。

也可以使用you should not use localStorage to store your tokens或Cookies。相反,可以使用标准的OAuth协议(专用服务(如Okta,Auth0或开放源代码替代品提供专门用于此目的的SDK))进行检索。

例如使用Auth0 SDK

  

为什么令牌没有存储在浏览器存储器中?从历史上看,   将令牌存储在本地或会话存储中是常见的。但是,浏览器   存储不是存储敏感数据的安全场所。的   auth0-spa-js SDK为您管理会话检索,因此您无需   不再需要在浏览器存储中存储敏感数据,以便   刷新单页应用程序后恢复会话。

     

使用auth0-spa-js,我们可以在以下情况下简单地从SDK请求令牌:   我们需要它(例如,在HTTP拦截器中)而不是存储它   在Angular应用或浏览器中本地进行。 SDK管理令牌的新鲜度   同样,因此我们无需担心令牌更新时   过期。

注意:我不隶属于Auth0,只是在我的最新项目中使用了该服务:)

答案 1 :(得分:-1)

等待的一种方式是通过Promises-承诺直到您的身份验证返回后才能解决,然后等待该承诺,然后再从localStorage访问令牌。