首页 文章

Angular 4:无法从响应中读取标头 - 而不是CORS问题

提问于
浏览
1

在服务器自动更新令牌的上下文中,我正在努力解决基本问题:从响应中获取头数据 .

它似乎与CORS无关,因为我的Node / express allwos授权/ x-access-token并相应地响应(请参阅下面的网络选项卡screeencap) .

我希望看到工作的第一步是简单地从响应中读取 Headers . 查看我的代码,它是文档中的样板文件 . 获取“Content-Length”的事件返回null .

auth-service.ts

login(username:string, password:string):Observable<boolean>{
    this.loggedIn = false;
    return new Observable( (observer:Observer<boolean>) => {

      const body = {user: username, pwd: password};
      const url = this.config.API_ENDPOINT_PUBLIC_AUTH;

      this.httpClient.post(url, body, {
        responseType: 'text',
        observe: "response"
      }).first().subscribe(
        (response:HttpResponse<string>) => {

          // DEBUG
          console.log(response.headers.get('Authorization'));
          console.log(response.headers.get('X-Test-Header'));
          console.log(response.headers.get('Content-length'));


          this.token = response.headers.get('Authorization');
          this.storeToken(this.token);
          this.currentUser = username;
          this.loggedIn = true;
          this.authChanged$.next('auth');
          observer.next(true);
        },
        (err) => observer.next(false),
        () => {},
      );
    });
  }

控制台输出:

null null null

将此与此请求的网络选项卡的内容进行比较:

enter image description here

不用说我的HttpInterceptor也不起作用 - 在响应中提供“Authorization”标头时,它将该值用作新标记 . 这样可以实现令牌的自动续订:

token.interceptor.ts

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    const authService = this.injector.get(AuthService);
    const token = authService.getToken();

    if(token){
      request = request.clone({
        setHeaders: { 'x-access-token' : token }
      });
    }

    return next.handle(request).do(
      (event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
          const response:HttpResponse<any> = (<HttpResponse<any>> event);
          const authorizationHeader = response.headers.get('Authorization');
          console.log('Authorization header value: ' + authorizationHeader);
          if(authorizationHeader){
            authService.setToken(authorizationHeader);
          }
        }
      },
      (err: any) => {
      if (err instanceof HttpErrorResponse){
        if (err.status === 401) {
          this.router.navigate(['/']);
        }
      }
    });
  }

1 回答

  • 5

    好的,这就是答案:我使用Node.js / Express作为后端,即使 Headers 在Chrome的网络标签中可见,也不会使它们可供Angular处理 .

    “他们怎么可见但却无法使用?”我还不清楚 .

    配置您的Node / Express应用程序(查找评论“SOLUTION HERE”):

    function configureExpress(expressApp){  
        expressApp.use(bodyparser.urlencoded({ extended: true }));
        expressApp.use(bodyparser.json());
    
        // Middleware: Use CORS, add headers and allow methods
        expressApp.use(expressMiddleware);
    }
    
    function expressMiddleware(req, res, next) {
    
        // Request origin: Allow ALL
        res.header("Access-Control-Allow-Origin", "*");
    
        // Allowed headers
        res.header("Access-Control-Allow-Headers",
    
            "Origin"
            +",X-Requested-With"   // Dont allow AJAX CORS without server consent - see http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header
            +",x-access-token"
            +",Content-Type"
            +",Authorization"
            +",Accept"
        );
    
        // SOLUTION HERE
        // Allow headers access
        res.header("access-control-expose-headers",
            ",Authorization"
            +",Content-Length"
            );
    
        // Allowed methods
        res.header('Access-Control-Allow-Methods',
            'GET,'
            +',POST'
            +',OPTIONS'
            +',PUT,'
            +',DELETE'
        );
    
        // Handle CORS requests: cross-domain/origin requests will begin with an OPTION request to the same endpoint.
        if('OPTIONS' === req.method){
            res.sendStatus(200);
        }
    
        else{
            // Request validations complete
            next();
        }
    }
    

相关问题