无法使用授权标头执行发布请求
Posted
技术标签:
【中文标题】无法使用授权标头执行发布请求【英文标题】: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… 是真的吗? 【参考方案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();
);
)
【讨论】:
以上是关于无法使用授权标头执行发布请求的主要内容,如果未能解决你的问题,请参考以下文章
如果授权标头不存在,则无法在 Webfilter 中发送自定义正文