Angular HttpClient未设置Authorization标头

时间:2018-03-19 15:53:36

标签: angular http

我见过其他几个这样的问题,但是他们没有解决这个问题。我使用MailChimp的API进行简单调用,在注册时将成员添加到我的邮件列表中。

然而,当我测试时,我获得了401未授权,并且API抱怨没有提交API密钥。当我在Chrome中检查请求时,我看不到任何授权标头。这是我的代码:

        const formData = {
            email_address: this.emailControl.value,
            status: 'subscribed',
            merge_fields: {
                NAME: this.nameControl.value
            }
        };
        const header = new HttpHeaders({
            'Authorization': 'apikey:' + environment.mailChimpApiKey
        });

        this.http.post(this.mailChimpUrl, formData, {
            headers: header,
            observe: 'response'
        }).subscribe(response => {
            console.log('response', response);
            if (response.status === 200) {
                this.submitted = true;
            }
        });

我检查并仔细检查了HttpClient.post方法签名,以及MailChimp API期望如何接收Auth头。看起来我做的一切都正确,那么为什么Angular不设置标题?

我注意到,当我设置可选标头时,值仅会更改为Access-Control-Request-Headers。我读错了Chrome控制台吗?

enter image description here

Angular版本:5.2.4

4 个答案:

答案 0 :(得分:3)

问题不在于Angular。现代浏览器为大多数跨域请求发送preflight OPTIONS request,而Mailchimp不支持这些请求。 Mailchimp API不支持客户端实现:

  

MailChimp不支持使用我们的API的客户端实现   CORS请求由于暴露帐户的潜在安全风险   API密钥。

如果更明显地说明这一点会很好,但我一开始并没有注意到它。最好的解决方案是使用jsonp。

答案 1 :(得分:1)

要执行此操作,我们需要从RequestOptions库中导入Http@angular/http以及withCredentials : true

正如@Maciej建议您也可以将import { Injectable } from '@angular/core'; import { Http, Headers, Response, RequestOptions } from '@angular/http'; @Injectable() export class ApplicationService { constructor(private http: Http) { } myformPost(id:number, formData : any){ let header = this.initHeaders(); let options = new RequestOptions({ headers: header, method: 'post'}); let body = JSON.stringify(formData); return this.http.post(this.myapiUrl, body, options) .map(res => { return res.json(); }) .catch(this.handleError.bind(this)); } private initHeaders(): Headers { var headers = new Headers(); let token = localstorage.getItem(StorageKey.USER_TOKEN); if (token !== null) { headers.append('Authorization', token); } headers.append('Pragma', 'no-cache'); headers.append('Content-Type', 'application/json'); headers.append('Access-Control-Allow-Origin', '*'); return headers; } private handleError(error: any): Observable<any> { return Observable.throw(error.message || error); } } 用于您的请求选项。

  

ApplicationService.ts

 CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '10.50.10.117', '62378' )
 CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '10.50.10.117', '62388' )

答案 2 :(得分:0)

从屏幕截图中,我假设您正在提出OPTIONS请求,而不是POST

可能问题出在服务器端。看看这个答案:http post - how to send Authorization header?

您还应该考虑在您的请求选项中添加withCredentials

const formData = {
            email_address: this.emailControl.value,
            status: 'subscribed',
            merge_fields: {
                NAME: this.nameControl.value
            }
        };
        const header = new HttpHeaders({
            'Authorization': 'apikey:' + environment.mailChimpApiKey
        });

        this.http.post(this.mailChimpUrl, formData, {
            headers: header,
            observe: 'response',
            withCredentials: true
        }).subscribe(response => {
            console.log('response', response);
            if (response.status === 200) {
                this.submitted = true;
            }
        });

根据documentation

  

withCredentials:boolean | null

     

启用请求的使用凭据。

答案 3 :(得分:0)

我非常愿意评论原始海报的答案,因为我认为这是正确的,澄清评论可能有助于该人获得+1回答。

所以......

如果我在angular和我的两个域之间运行代码并使用say节点来提供数据,我必须在节点服务器的开发过程中输入以下内容。我最初这样做是为了确保所有人都在开发中工作。

app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, 
PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true); //
next();

});

这会清除您的错误,但是对于交叉脚本来说太开放了,您可以阅读如何允许特定域等访问它而不是此处提供的*。