【问题标题】:Angular HttpClient not setting Authorization header [duplicate]Angular HttpClient未设置授权标头[重复]
【发布时间】:2018-08-28 06:18:22
【问题描述】:

我已经看到了其他几个类似的问题,但它们并没有解决问题。我使用 MailChimp 的 API 进行了一个简单的调用,以便在他们注册时将成员添加到我的邮件列表中。

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

        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 控制台?

Angular 版本:5.2.4

【问题讨论】:

    标签: angular http


    【解决方案1】:

    从屏幕截图中,我假设您发出的是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: 布尔值 |空

    为请求启用使用凭据。

    【讨论】:

    • 很奇怪。它仍然没有添加标题。或我尝试的任何其他测试标头。还有其他我应该注意的奇怪问题吗?
    • 我正在检查angular.io/guide/http#adding-headers,我认为您的要求一切正常...
    • 这很愚蠢,但也许您需要单独创建 RequestOptions,而不是“即时”创建。或者至少将这个对象 {headers: 'someHeader'} 'cast' 为 RequestOptions ?
    • 我添加了一个截图,它实际上不是设置标题,而是Access-Control-Request-Headers 中的值,这似乎是一个线索
    • 这不是 Angular。它是浏览器:)
    【解决方案2】:

    我非常希望对原始发帖人的答案发表评论,因为我认为它是正确的,并且澄清评论可能会帮助该人获得 +1 的答案。

    所以..

    如果我在 angular 和我的两个域之间运行代码并使用 say node 来提供数据,我必须在节点服务器中的开发过程中输入以下内容。起初我这样做非常开放,以确保一切都在开发中工作。

    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();
    

    });

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

    【讨论】:

      【解决方案3】:

      为此,我们需要从@angular/http 库中导入HeadersRequestOptions 以及Http

      正如@Maciej 建议的那样,您也可以将withCredentials : true 用于您的请求选项。

      ApplicationService.ts

      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);
        }             
      }
      

      【讨论】:

        【解决方案4】:

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

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

        如果说得更清楚一点就好了,但我一开始并没有注意到。最好的解决方案是使用jsonp。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-29
          • 1970-01-01
          • 2013-01-15
          • 2021-11-21
          相关资源
          最近更新 更多