ajax——CORS跨域调用REST API 的常见问题以及前后端的设置
RESTful架构是目前比较流行的一种互联网软件架构,在此架构之下的浏览器前端和手机端能共用后端接口。
但是涉及到js跨域调用接口总是很头疼,下边就跟着chrome的报错信息一起来解决一下。
假设:前端域名为front.ls-la.me
,后端域名为api.ls-la.com
。前端需要访问的接口为http://api.ls-la.com/user/info.json
,需要用GET方式访问。
现在,用Ajax向后端发送请求,得到第一个错误。(cors跨域的写法参考:http://blog.csdn.net/fdipzone/article/details/46390573)
错误1:
XMLHttpRequest cannot load http://api.ls-la.com/user/info.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://api.ls-la.com' is therefore not allowed access.
提示响应头没有Access-Control-Allow-Origin
这一项,谷歌得知需要在服务器指定哪些域名可以访问后端接口,设定之:
header('Access-Control-Allow-Origin: http://front.ls-la.me');
// 如果你不怕扣工资可以这么设:header('Access-Control-Allow-Origin: *');
再次发送请求,又报错。
错误2:
XMLHttpRequest cannot load http://api.ls-la.com/user/info.json. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.
意思是ajax头信息中有X-Requested-With
这一字段,后端不允许。那就让允许吧:
header('Access-Control-Allow-Headers: X-Requested-With');
好了,这下不报错了,但是仔细分析请求过程,发现浏览器向接口地址发送了两个请求,第一个是OPTIONS
方式,第二个才是GET
方式。
这里的第一个请求叫做“Preflight Table Request(预检表请求,微软这么翻译的,不知道对不对)”。这个请求是在跨域的时候浏览器自行发起的,作用就是先请求一下看看服务器支不支持当前的访问。如果不支持,就会报之前所列的错误;如果支持,再发送正常的GET请求,返回相应的数据。
但是每个请求之前都要这么OPTIONS一下,作为典型处女座表示非常不能忍。需要告诉浏览器你搞一下是个意思,老这么搞就没意思了:
// 告诉浏览器我支持这些方法(后端不支持的方法可以从这里移除,当然你也可以在后边加上OPTIONS方法。。。)
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE');
// 告诉浏览器我已经记得你了,一天之内不要再发送OPTIONS请求了
header('Access-Control-Max-Age: ' . 3600 * 24);
好了,事情至此告一段落。
才怪!
突然有一天测试妹子跑来跟你说网站记不住用户的状态,一检查发现跨域的时候cookie失效了。
错误3:
js在发送跨域请求的时候请求头里默认是不带cookie的,需要让他带上:
// js
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.ls-la.com/user/info.json');
xhr.withCredentials = true;
xhr.onload = onLoadHandler;
xhr.send(); // jQuery
$.ajax({
url: 'http://api.ls-la.com/user/info.json',
xhrFields: {
withCredentials: true
},
crossDomain: true,
}); // Angular 三选一
$http.post(url, {withCredentials: true, ...})
$http({withCredentials: true, ...}).post(...)
app.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
}
总之就是要在xhr里设置一下withCredentials = true
,然后跨域请求就能带上cookie了。注意这里的cookie遵循同源策略,也就是后端发送的cookie也是属于域名api.ls-la.com
的。
发送一个带cookie的post请求,依旧报错:
错误4:
XMLHttpRequest cannot load http://api.ls-la.com/user/info.json. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
跟上边那个X-Requested-With
报错一样,头信息不允许,后端改下:
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type');
再来,还是报错:
错误5:
XMLHttpRequest cannot load http://api.ls-la.com/user/info.json. Response to preflight request doesn't pass access control check: Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://front.ls-la.me' is therefore not allowed access.
提示很明显,后端代码加一行,允许携带cookie访问:
// 允许前端带cookie访问
header('Access-Control-Allow-Credentials: true');
总结
在后端程序加载前执行以下函数,避免OPTIONS请求浪费系统资源和数据库资源。
function cors_options()
{
header('Access-Control-Allow-Origin: http://front.ls-la.me');
header('Access-Control-Allow-Credentials: true'); if('OPTIONS' != $_SERVER['REQUEST_METHOD']) return; header('Access-Control-Allow-Headers: X-Requested-With, Content-Type');
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE');
header('Access-Control-Max-Age: ' . 3600 * 24); exit;
}
参考:
预检表请求
Cross-Origin Resource Sharing
Angular通过CORS实现跨域方案 注意这里的[CORS的分类]一节。
ajax——CORS跨域调用REST API 的常见问题以及前后端的设置的更多相关文章
- 以短链服务为例,探讨免AppKey、免认证、Ajax跨域调用新浪微博API
新浪微博的API官方提供了很多种调用方式,支持编程的,归根结底就是两种: 1.基于Oauth协议,使用Open API.(http://open.weibo.com/wiki/%E6%8E%88%E6 ...
- jQuery跨域调用Web API
我曾经发表了一篇关于如何开发Web API的博客,链接地址:http://www.cnblogs.com/guwei4037/p/3603818.html.有朋友说开发是会开发了,但不知道怎么调用啊? ...
- javascript ajax 脚本跨域调用全解析
javascript ajax 脚本跨域调用全解析 今天终于有点时间研究了一下javsscript ajax 脚本跨域调用的问题,先在网上随便搜了一下找到一些解决的办法,但是都比较复杂.由是转到jqu ...
- 改变mvc web api 支持android ,ios ,ajax等方式跨域调用
公司一个移动后端的项目用到了 webapi 项目搭建到外网环境共app开发者调用测试接口时遇到了一个问题 接口不允许跨域调用 .查阅资料明白 同源策略原则根据请求报头值 Origin 与回应报头值 A ...
- jquery ajax jsonp跨域调用实例代码
今天研究了AJAX使用JSONP进行跨域调用的方法,发现使用GET方式和POST方式都可以进行跨域调用,这里简单分享下,方便需要的朋友 客户端代码 复制代码 代码如下: <%@ Page Lan ...
- jquery ajax 无法跨域调用的解决办法
今天要用到jquery ajax 跨域调用,但是ajax是禁止跨域调用的,所以只能先在php文件使用函数取得跨域的值,然后用ajax调用本地php文件.
- jquery ajax CORS 跨域訪问 WebService
JS代码: var word = document.getElementById("word").value; $.ajax({ type: "POST", c ...
- 关于AJAX跨域和原生AJAX CORS跨域解决
项目需求要在别人的域名下调用自己的接口,因为浏览器的同源策略是不允许不同域名下之间的信息交换,那就意味着要跨域处理 参考博客 :https://blog.csdn.net/Ulricalin/arti ...
- ajax jsonp跨域 【转】
跨域的基本原理: JSONP跨域GET请求是一个常用的解决方案, JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的 ...
随机推荐
- 学写js Calender控件
好几个月没写博客了,一直在赶项目.项目现在终于处于稳定的状态,只是修修改改.作为后台程序员的我真是苦逼啊,从web到手机端接口我都得写,杂七杂八的事情...这两天终于闲下来了,没事儿看了一下关于js日 ...
- CentOS升级openssl
才设置了http2,结果蓝狗说我网站不安全,检测一下发现openssl有漏洞,于是准备升级一下openssl 检测网站: www.ssllabs.com/ssltest/analyze.html # ...
- 【原】iOS 同时重写setter和getter时候报错:Use of undeclared identifier '_name';did you mean 'name'
写了那么多的代码了,平时也没有怎么注意会报这个错误,因为平时都很少同时重写setter和getter方法,一般的话,我们大概都是使用懒加载方法,然后重写getter方法,做一个非空判断.然后有时候根据 ...
- Django进阶(一)
Url进阶 mysit/mysit/urls.py from django.conf.urls import url from django.contrib import admin urlpatte ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- SSH免密码登陆原理
Master作为客户端,要实现无密码公钥认证,连接到服务器Salve上时,需要在Master上生成一个密钥对,包括一个公钥和一个私钥,而后将公钥复制到所有的Salve上.当Master通过SSH链接到 ...
- NodeJS 学习总结 01 安装配置
1 安装NodeJS 具体参考已发布的文章Ubuntu学习总结-07 Nodejs和npm的安装 2 使用淘宝 NPM 镜像 国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像 ...
- loss function
什么是loss? loss: loss是我们用来对模型满意程度的指标.loss设计的原则是:模型越好loss越低,模型越差loss越高,但也有过拟合的情况. loss function: 在分 ...
- nginx本地转发
在conf文件下找到nginx.conf配置文件:添加如下代码:
- openstack资料相关
https://github.com/int32bit/openstack-workflow #openstack各种时序图 http://docs.openstack.org/developer/ ...