Ionic 2 / Angular 2 / CORS:HTTP 标头未随请求一起发送

Posted

技术标签:

【中文标题】Ionic 2 / Angular 2 / CORS:HTTP 标头未随请求一起发送【英文标题】:Ionic 2 / Angular 2 / CORS: HTTP Headers not being sent with request 【发布时间】:2016-12-11 01:31:42 【问题描述】:

我正在使用 Ionic 2 (2.0.0-beta.10) 开发一个项目。我尝试通过请求传递授权令牌。但是没有发送标头。我试图通过请求传递的其他标头也没有被发送。

let url = 'http://www.example.com/savedata';
let data = JSON.stringify( email: 'test@test.com', password: '123456' );

let headers = new Headers();

headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + "tokenContent");

let options = new RequestOptions( headers: headers );

this.http.post(url, data, options).map(res => res.json()).subscribe(data => 

                console.log("it worked");

, error => 
                console.log("Oooops!");
);

我的 REST API 收到带有以下标头的请求:

Host:               www.example.com 
Connection:         keep-alive  
Access-Control-Request-Method:  POST    
Origin:             http://evil.com/    
User-Agent:         Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/51.0.2704.106 Safari/537.36   
Access-Control-Request-Headers: authorization, content-type 
Accept:             */* 
Referer:            http://localhost:8100/?restart=794567   
Accept-Encoding:        gzip, deflate, sdch 
Accept-Language:        en-US,en;q=0.8  

数据(正文)正确,只有我无法解决的标题问题。 任何帮助将不胜感激。

【问题讨论】:

你能尝试传递这样的标题吗this.http.post(url, data, headers:headers).... 我尝试这样做,但是在发送请求时我在 REST API 中收到的标头如下: Host www.example.com Connection keep-alive Content-Length 45 Origin evil.com User -Agent Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 Content-Type text/plain Accept / Referer localhost:8100/?restart=794567 Accept-编码 gzip,放缩 Accept-Language en-US,en;q=0.8 好的,检查这个答案***.com/questions/38301878/… 谢谢,我确实已经阅读了这个问题。然而,没有一个答案实际上描述了这个问题的解决方案。根据 Bala Abhinav 的说法,他设法解决了这个问题,但他没有提到如何......“这个问题是一个 CORS 问题。现在已经解决了。谢谢。——Bala Abhinav” 您是否设置了在您的 REST API 中授权的标头? Access-Control-Allow-Headers: Authorization 【参考方案1】:

尝试使用HttpClient。它是最简单和最新的。

constructor(private http: HttpClient) 
...
...

postData() 
   const httpHeaders = new HttpHeaders(
    'Content-Type' : 'application/json',
    'Cache-Control': 'no-cache',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Credentials': 'true',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, DELETE',
    'Access-Control-Allow-Headers': 'Origin, Accept, Access-Control-Allow-Origin, Content-Type, Authorization, X-Requested-With'
    );

   let url = 'http://www.example.com/savedata';
   let data = JSON.stringify( email: 'test@test.com', password: '123456' );


   this.http.post(url, data,  headers: httpHeaders, observe: 'response').subscribe(data =>     
                console.log("it worked");    
   , error => 
                console.log("Oooops!");
   ); // Here you don't need to use map().

【讨论】:

【参考方案2】:

这个问题在这里有答案: https://***.com/a/45286959/4119650

Headers.append() 不更新对象,它返回它的克隆。通过实例化 Headers 对象然后调用 headers.append()append 的结果不会被使用。 相反,您可能需要这样做:

headers: Headers = new Headers().append('Content-Type', 'application/json').append('Authorization', 'Bearer ' + "tokenContent");

Headers 无论如何都已弃用,应替换为 HttpHeadersHttpClient。 https://angular.io/api/common/http/HttpHeaders https://angular.io/guide/http

【讨论】:

【参考方案3】:

对于发送和接收,您可能正在使用一台服务器,例如:nginx 在为后端启用站点的配置文件中,您必须添加 Access-Control-Allow-Origin: * 或 http://localhost 这可能会有所帮助。

【讨论】:

【参考方案4】:

Stringify JSON 这并不是在任何时候都有效。 首先,您需要将您的 JSON 数据转换为 StringQuery,以便服务器能够正确且更快地理解。

public StringQuery(jsonString) 
        return Object.keys(jsonString).map(function (key) 
          return encodeURIComponent(key) + '=' + encodeURIComponent(jsonString[key]);
        ).join('&');
         

然后你做你的帖子功能或方法

public post()
let url = 'http://www.example.com/savedata';
let data = this.StringQuery( email: 'test@test.com', password: '123456' )




    let headers = new Headers();

    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Authorization', 'Bearer ' + "tokenContent");

    let options = new RequestOptions( headers: headers );

    this.http.post(url, data, options).map(res => res.json()).subscribe(data => 

                    console.log("it worked");

    , error => 
                    console.log("Oooops!");
    );

我也使用此代码并获得成功的发布请求。

【讨论】:

【参考方案5】:

如果您调用的 REST API(示例中为 example.com)与您的 Angular 2 / Ionic 应用程序(示例中为 evil.com)位于不同的域中,那么您需要配置 REST API 服务器以返回这个标题:

Access-Control-Allow-Origin: http://evil.com 

这将允许浏览器将异步 HTTP 请求从 evil.com 主机发送到其余 api 服务器。

这是通过在 rest api 服务器上启用 CORS 来完成的,您可以阅读更多内容。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

支持跨源请求的多个后端库:

https://github.com/expressjs/cors - NodeJS/Express

https://pypi.python.org/pypi/Flask-Cors/ - Flask 的 Python cors 库

这个列表几乎适用于任何其他后端框架。

【讨论】:

以上是关于Ionic 2 / Angular 2 / CORS:HTTP 标头未随请求一起发送的主要内容,如果未能解决你的问题,请参考以下文章

访问父视图属性的最佳方式(Ionic 2、Angular 2)

包括 ionic 2/angular 2 的通用标题栏

使用 angular 2/ionic 2 限制字符串的长度

使用 ionic 2 和 angular 2 创建菜单

带有 Ionic 2 Angular 2 和 TypeScript 的 OpenPGP

Ionic 2 / Angular 2 中的全局函数