【问题标题】:unable to execute post request with authorization header无法使用授权标头执行发布请求
【发布时间】:2018-01-15 23:46:14
【问题描述】:

当我发布带有授权标头的请求 API 时,我在 Angular 4 中遇到问题?

addPost(body): Observable<any>{
      const url = 'https://xxxxxx';

     return this.http.post(URL, body, this.options)
     .map((res:Response) => {
     this.data = res.json();
     })
}

token 来自 firebase 身份验证

afAuth.auth.currentUser.getIdToken()
    .then(token => {
        this.headers = new Headers({
            'Authorization': 'Bearer '+token
        });
        this.headers.append('Content-Type', 'application/json');
        this.options = new RequestOptions({ headers: this.headers });
    });
this.headers.append('Content-Type', 'application/json');
this.options = new RequestOptions({ headers: this.headers });

我用这个打电话发帖

return this.getJob.addPost(body).subscribe((data) => {
    console.log(data);
});

响应 403!!!

请求网址:https://us-central1-xxxxxx-prod.cloudfunctions.net/api/post 请求方法:OPTIONS
状态码:403
远程地址:216.58.198.51:443
推荐人政策:no-referrer-when-downgrade
响应标头
访问控制允许方法:GET、POST
访问控制允许来源:
缓存控制:私有
内容编码:gzip
内容长度:32
内容类型:文本/html;字符集=utf-8
日期:格林威治标准时间 2017 年 8 月 8 日星期二 12:23:55
etag:W/"c-dAuDFQrdjS3hezqxDTNgW7AOlYk"
函数执行 ID:d0la00v58w7p
服务器:谷歌前端
状态:403
变化:接受编码
x-cloud-trace-context:d1b6ff9d729f7e250193a70aea16cac1;o=1
x-cloud-trace-context:d1b6ff9d729f7e250193a70aea16cac1
x-powered-by:Express
请求标头
:authority:us-central1-xxxxxx-prod.cloudfunctions.net
:method:OPTIONS
:path:/api/post
:scheme:https
接受:
/*
接受编码:gzip,放气,br
接受语言:en-US,en;q=0.8,ar;q=0.6
访问控制请求标头:授权、内容类型
访问控制请求方法:POST
alexatoolbar-alx_ns_ph:AlexaToolbar/alx-4.0.1
缓存控制:无缓存
来源:http://localhost:8080
编译指示:无缓存
推荐人:http://localhost:8080/extras/addjobpost
用户代理:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/59.0.3071.115 Safari/537.36

【问题讨论】:

  • 解决这个问题的更好方法是创建一个扩展 Angular 的 http 模块的拦截器
  • console 选项返回这个 RequestOptions {method: null, headers: Headers, body: null, url: null, params: undefined…} 是真的吗?

标签: angular http http-headers http-post


【解决方案1】:

更好的方法是创建一个扩展默认 http 模块的拦截器

创建一个interceptor.ts

import {
    Http,
    Request,
    RequestOptionsArgs,
    Response,
    RequestOptions,
    ConnectionBackend,
    Headers
}
    from '@angular/http';

import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class HttpInterceptor extends Http {

    constructor(private backend: ConnectionBackend, private defaultOptions: RequestOptions, private router: Router) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.request(url, this.getRequestOptionArgs(options)));
    }

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.get(url, this.getRequestOptionArgs(options)));
    }

    post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
    }

    put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
    }

    delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.delete(url, this.getRequestOptionArgs(options)));
    }

    getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
        if (options === null) {
            options = new RequestOptions();
        }

        if (options === undefined) {
            options = new RequestOptions();
        }

        let headers = new Headers();
        let key = 'auth.jwt.token';
        let item = localStorage.getItem(key) ? localStorage.getItem(key) : null;
        let parsedToken = JSON.parse(item);

        headers.append('Authorization', 'Bearer ' + parsedToken.token);
        if(options.headers) {
          headers.append('Content-Type', 'multipart/form-data');
          headers.append('accept', 'application/json');
        } else {
          headers.append('Content-Type', 'application/json');
        }
        //Clearing the headers and appending the token + content type every request.
        options.headers = new Headers();

        options.headers = headers;

        return options;
    }

    intercept(observable: Observable<Response>): Observable<Response> {
        return observable.catch((err, source) => {
            if (err.status === 401 && !err.endsWith(err.url, 'api/auth/login')) {
                this.router.navigate(['/login']);
                return Observable.empty();
            } else {
                return Observable.throw(err);
            }
        });

    }
}

在你的app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common';
import { XHRBackend, RequestOptions, Http, HttpModule } from '@angular/http';
import { Router } from '@angular/router';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpInterceptor } from 'interceptor.ts';

export function httpInterceptorFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions, router: Router) {
  return new HttpInterceptor(xhrBackend, requestOptions, router);
}
@NgModule({
    imports: [BrowserModule, AppRoutingModule, HttpModule, SharedModule.forRoot()],
    declarations: [AppComponent],
    providers: [{
        provide: APP_BASE_HREF,
        useValue: '<%= APP_BASE %>'
    }, SomeService, AnotherService, 
    {
        provide: Http,
        useFactory: httpInterceptorFactory,
        deps: [XHRBackend, RequestOptions, Router]
    }],
    bootstrap: [AppComponent]
})
export class AppModule { }

然后像往常一样调用http,例如this._http.get().map(),拦截器会为你附加令牌。

编辑:

更新的答案包括基本的app.module.ts

【讨论】:

  • useFactory 未定义
  • 更新了我的答案以包含整个 app.module.ts,我想您只需告诉您添加提供程序即可了解如何操作...
  • console 选项返回这个 RequestOptions {method: null, headers: Headers, body: null, url: null, params: undefined…} 是真的吗?
【解决方案2】:

请使用下面的代码。

let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
headers.append('Authorization', 'Bearer ' + 'token');

let order = 'order=foobar';
console.log("data");

 return this.http.post(url, body, { headers: headers })
     .map((res: any) => res.json());

【讨论】:

  • 这不是登录。我使用邮递员和令牌启动'Bearer'+令牌
  • 这是一个post请求的例子。不用担心..编辑答案请检查。
  • console 选项返回这个 RequestOptions {method: null, headers: Headers, body: null, url: null, params: undefined…} 是真的吗?
【解决方案3】:

我将标题替换为参数

getTokenHeader() {
    return this.afAuth.auth.currentUser.getIdToken()
    .then(token => {
        let params = new URLSearchParams();
        params.set('tsid', `Bearer ${token}`);
        return params;
    });
}

并在这个函数中调用getTokenHeader

    addPost(body): Observable<any>{//
        // const url = 'https://us-central1-talentdraw-prod.cloudfunctions.net/api/post';
        let url = this.api.URL['main']+this.api.URL['afterAuth'];

        return new Observable(observer => {
            this.getTokenHeader()
            .then(tokenOptions => {
                // console.log(tokenOptions);

                return this.http.get(url, { 
                    search: tokenOptions
                    })
                    .map((res:Response) => {
                        // this.data = res.json().data;
                        observer.next(res);
                        observer.complete();
                    })
                    .subscribe((data) => {
                        observer.complete();
                    })
                })
                .catch(( error: any ) => {
                    observer.error(error);
                    observer.complete();
                });
        })
    }

【讨论】:

    猜你喜欢
    • 2017-11-09
    • 2021-02-10
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 2022-10-16
    • 2020-05-22
    • 2016-06-27
    相关资源
    最近更新 更多