如何解决 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
做同样的事情时,它给了我CORS
和JSONP
错误..
有人可以帮我吗..
我之前的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 extensions
和plugins
在chrome
和mozilla
上运行。还是没有成功。
我不知道我的代码是错误的还是其他重要的问题。
编辑:按照以下两个 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 问题的主要内容,如果未能解决你的问题,请参考以下文章
Ionic 2 / Angular 2 / CORS:HTTP 标头未随请求一起发送
如何解决 Laravel + Nuxt.js 中的 CORS 错误