如何解决 Ionic2 中的 CORS 问题和 JSONP 问题

Posted

技术标签:

【中文标题】如何解决 Ionic2 中的 CORS 问题和 JSONP 问题【英文标题】:How to resolve CORS issue and JSONP issue in Ionic2 【发布时间】:2016-11-24 22:48:34 【问题描述】:

我是IONIC-2 的新手,想将我的移动应用程序连接到Odoo - open source ecommerce.. 这种连接涉及一些JSONP 请求。我之前通过jQuery 做过同样的事情。它在phonegap 应用程序中正常工作。但是当我用IONIC-2 做同样的事情时,它给了我CORSJSONP 错误..

有人可以帮我吗..

我之前的jQuery 代码是..

/******  index.js ******/

function json(url, params) 
   var deferred = jQuery.Deferred();

   uniq_id_counter += 1;
   var payload = 
      'jsonrpc': '2.0',
      'method': 'call',
      'params': params,
      'id': ("r" + uniq_id_counter)
   ;

   rpc_jsonp(url, payload).then(function (data, textStatus, jqXHR) 
      if (data.error) 
          deferred.reject(data.error);
      
      deferred.resolve(data.result, textStatus, jqXHR);
   );

   return deferred;
 


function rpc_jsonp(url, payload) 

   // extracted from payload to set on the url
   var data = 
      session_id: window.localStorage.getItem("session_id"),
      id: payload.id
   ;

   var ajax = 
     type: "POST",
     dataType: 'jsonp',
     jsonp: 'jsonp',
     cache: false,
     data: data,
     url: url
  ;

  var payload_str = JSON.stringify(payload);
  var payload_url = jQuery.param(r: payload_str);
  if (payload_url.length < 2000) 
       //  throw new Error("Payload is too big.");
  

  console.log(ajax);
  ajax.data.r = payload_str;
  console.log(ajax);
  return jQuery.ajax(ajax);


/******  index.js ******/

我在上面调用custom json函数Login.html文件..

 /******  login.html ******/

 function login()

   var base_url = 'MY_SERVER_URL';
   json(base_url+'web/session/authenticate', 
      'base_location': base_url,
      'db':'myDB',
      'login': 'admin',
      'password':'admin'
   ).done(function (data) 

   if(data.uid != false)
       alert(data);
   
   else
       alert('Invalid Username or Password.');
   

   deferred.resolve();
 ).fail(function(data)
     alert('Invalid Username or Password.');
 );

  return deferred;

/******  login.html ******/

我在创建service 时尝试了IONIC 2 中的代码

/****** OdooJsonService.ts ******/
import  Injectable  from '@angular/core';
import  Http, Jsonp, JSONP_PROVIDERS, Headers, RequestOptions  from '@angular/http';
import  Observable  from 'rxjs/Observable';
import 'rxjs/Rx';

@Injectable()
export class OdooJsonService 
//data: any;
uniq_id_counter: number;
payload: any;
result_rpc: any;

constructor(private http: Http, private jsonp: Jsonp) 
  this.http = http;
  //this.data = null;


json(url, params) 

    this.uniq_id_counter = this.uniq_id_counter + 1;

    this.payload = JSON.stringify(
        'jsonrpc': '2.0',
        'method': 'call',
        'params': params,
        'id': ("r" + this.uniq_id_counter)
    );

    return this.rpc_jsonp(url, this.payload)
                    .map(res => res.json())
                    .catch(this.handleErrorOne);


rpc_jsonp(url, payload) 

    let data = JSON.stringify(
        //session_id: window.localStorage.getItem("session_id"),
        id: payload.id
    );

    let ajax = JSON.stringify(
        type: 'POST',
        dataType: 'jsonp',
        jsonp: 'jsonp',
        cache: false,
        data: data,
        url: url
    );

    let headers = new Headers( 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*',
                                'Access-Control-Allow-Methods': 'PUT, GET, POST',
                                'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept');
    let options = new RequestOptions( headers: headers );

    return this.http.post(url, ajax, options)
        .map(res => res.json())
        .catch(this.handleErrorTwo);


handleErrorOne(error) 
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');


handleErrorTwo(error) 
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');


        // End of OdooJsonService
 /****** OdooJsonService.ts ******/

我在Login.ts中使用service以上

/****** login.ts ******/
import  Component  from '@angular/core';
import  App, NavController, MenuController, ViewController  from 'ionic-angular';
import  TaskListPage  from '../task-list/task-list';

import  Http, Jsonp, JSONP_PROVIDERS  from '@angular/http';
import  OdooJsonService  from '../../providers/odoo-json-service/odoo-json-service';

@Component(
  templateUrl: 'build/pages/login/login.html',
  providers: [OdooJsonService, JSONP_PROVIDERS]
)
export class LoginPage 
   public data: any;

   constructor(private nav: NavController, public odooJsonService: OdooJsonService) 
     this.odooMethod();
   

   odooMethod() 
      this.odooJsonService
            .json('MY_SERVER_URL/web/session/authenticate', 'base_location': 'MY_SERVER_URL',
                    'db':'myDB', 'login': 'admin', 'password':'admin')
            .subscribe(odooData => 
                this.data = odooData;
                console.log(JSON.stringify(this.data));
            );
     


/****** login.ts ******/

控制台错误: (铬)

XMLHttpRequest cannot load https://MY_SERVER_URL/web/session/authenticate. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 500.

控制台错误:(firefox)

/web/session/authenticate: Function declared as capable of handling request of type 'json' but called with a request of type 'http'

我不确定这是否是正确的方法.. 任何人都可以指导以正确的顺序执行此操作..

我怎样才能在IONIC 2中达到同样的效果??

提前致谢。

【问题讨论】:

【参考方案1】:

我在同一个 url (localhost:8100) 上使用 ionic 和 iis 时遇到问题 这个 chrome 扩展帮助我解决了 cors 问题:[在此处输入链接描述]

https://chrome.google.com/webstore/detail/moesif-origin-cors-change/digfbfaphojjndkpccljibejjbppifbc

同样对于 web api,您可以将代码和平放在 web.config 文件中的 system.webServer 标记中

<system.webServer> 
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, 
DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
...
</system.webServer>

确保您的标题正确:

let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Access-Control-Allow-Origin','*');
headers.append('Access-Control-Allow-Methods','GET,PUT,POST,DELETE');
headers.append('Access-Control-Allow-Headers','Content-Type');

【讨论】:

【参考方案2】:

我在浏览器上使用CORS extensionspluginschromemozilla 上运行。还是没有成功。

我不知道我的代码是错误的还是其他重要的问题。

编辑:按照以下两个 cmets 在 MAC 机器上禁用 chrome 的网络安全。

【讨论】:

我解决了浏览器上的 CORS 问题,仅出于开发目的暂时禁用了 chrome 的网络安全。并更改了我的 JSONService 代码。 使用以下命令在 mac 机器上禁用 chrome 的网络安全。 open -n -a "Google Chrome" --args --user-data-dir=/tmp/temp_chrome_user_data_dir_for_cordova http://localhost:8100/index.html --disable-web-security 这会创建另一个禁用安全性的 chrome 实例。【参考方案3】:

您可以在 Chrome 中禁用同源策略。

    在您的桌面上创建一个单独的 chrome 图标。

    将该图标重命名为 chrome(x 域),以便您知道哪个是哪个。

    右键单击新图标并单击属性。

    将目标字段更改为"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-agent="android" --user-data-dir="C:/temp-chrome-eng"

    点击确定。

魔法发生在这里:

--disable-web-security

当您打开浏览器时,它将如下所示:

警告:仅用于测试目的,因为此浏览器已禁用安全功能。

【讨论】:

【参考方案4】:

您收到的错误是因为您的浏览器阻止了跨域 AJAX 请求(域未响应所需的标头)。但是,如果您在移动设备上执行应用程序,它应该可以工作,因为应用程序将直接执行请求。你可以阅读更多here。如果您在移动设备上启动该应用程序是否有效?

【讨论】:

库巴是正确的。在 android 或 ios 设备上运行您的应用程序时,它应该可以工作。但是,对于在浏览器中进行测试,请参阅下面的答案。 在设备上没有成功或错误日志。我不知道我的代码是错误的还是其他重要的东西。 我在使用 HTTPS 时遇到了问题,API 站点是否具有被 Android 接受的正确证书?如果可能,请先尝试使用 HTTP。并在代码中放置一个断点,以便您查看它是否实际执行。

以上是关于如何解决 Ionic2 中的 CORS 问题和 JSONP 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何解决Ionic2应用程序中的空白屏幕错误?

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

如何解决 Laravel + Nuxt.js 中的 CORS 错误

如何使用 http 解决 VUE 中的 CORS 问题?

如何使用 ASP.NET Core 解决 REACT 中的 CORS 错误

如何解决真实设备中的 CORS 问题?