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 的常见问题以及前后端的设置的更多相关文章

  1. 以短链服务为例,探讨免AppKey、免认证、Ajax跨域调用新浪微博API

    新浪微博的API官方提供了很多种调用方式,支持编程的,归根结底就是两种: 1.基于Oauth协议,使用Open API.(http://open.weibo.com/wiki/%E6%8E%88%E6 ...

  2. jQuery跨域调用Web API

    我曾经发表了一篇关于如何开发Web API的博客,链接地址:http://www.cnblogs.com/guwei4037/p/3603818.html.有朋友说开发是会开发了,但不知道怎么调用啊? ...

  3. javascript ajax 脚本跨域调用全解析

    javascript ajax 脚本跨域调用全解析 今天终于有点时间研究了一下javsscript ajax 脚本跨域调用的问题,先在网上随便搜了一下找到一些解决的办法,但是都比较复杂.由是转到jqu ...

  4. 改变mvc web api 支持android ,ios ,ajax等方式跨域调用

    公司一个移动后端的项目用到了 webapi 项目搭建到外网环境共app开发者调用测试接口时遇到了一个问题 接口不允许跨域调用 .查阅资料明白 同源策略原则根据请求报头值 Origin 与回应报头值 A ...

  5. jquery ajax jsonp跨域调用实例代码

    今天研究了AJAX使用JSONP进行跨域调用的方法,发现使用GET方式和POST方式都可以进行跨域调用,这里简单分享下,方便需要的朋友 客户端代码 复制代码 代码如下: <%@ Page Lan ...

  6. jquery ajax 无法跨域调用的解决办法

    今天要用到jquery ajax 跨域调用,但是ajax是禁止跨域调用的,所以只能先在php文件使用函数取得跨域的值,然后用ajax调用本地php文件.

  7. jquery ajax CORS 跨域訪问 WebService

    JS代码: var word = document.getElementById("word").value; $.ajax({ type: "POST", c ...

  8. 关于AJAX跨域和原生AJAX CORS跨域解决

    项目需求要在别人的域名下调用自己的接口,因为浏览器的同源策略是不允许不同域名下之间的信息交换,那就意味着要跨域处理 参考博客 :https://blog.csdn.net/Ulricalin/arti ...

  9. ajax jsonp跨域 【转】

    跨域的基本原理:    JSONP跨域GET请求是一个常用的解决方案,    JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的 ...

随机推荐

  1. python基础-面向对象进阶

    一.什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被 ...

  2. 递推 hdu 2064

    z[n] n个盘子从1到3次数 先想2个的时候  1->2 2->3  1->2 3->2 2->1 2->3 1->2 2->3 显然 要先把上面n- ...

  3. mysql在空闲8小时之后会断开连接(默认情况)

    调试程序的过程发现,在mysql连接空闲一定时间(默认8小时)之后会断开连接,需要重新连接,也引发我对重连机制的思考.

  4. ajax实现局部刷新

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  5. maven上传jar到nexus本地仓库

    一.nexus新增本地仓库 Hosted Repository:本地仓库,部署组织内部的版本内容 Proxy Repository:代理仓库,代理远程的公共仓库,如maven中央仓库 Virtual ...

  6. SWMM模型子汇水区划分的几种方法

    子汇水区的划分是SWMM模型建模的主要步骤之一,划分的好坏对结果精度有比较大的影响.概括来讲,子汇水区的划分有以下几种思路: (1)根据管网走向.建筑物和街道分布,直接人工划分子汇水区.这个方法适用于 ...

  7. HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth

    HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对 ...

  8. 火车头dede采集接口,图片加水印,远程图片本地化,远程无后缀的无图片本地化

    <?php /* [LocoySpider] (C)2005-2010 Lewell Inc. 火车采集器 DedeCMS 5.7 UTF8 文章发布接口 Update content: 图片加 ...

  9. python简单搭建HTTP Web服务器

    对于Python 2,简单搭建Web服务器,只需在i需要搭建Web服务器的目录(如C:/ 或 /home/klchang/)下,输入如下命令: python -m SimpleHTTPServer 8 ...

  10. git 命令操作

    git add .   : 将所有修改过的工作文件提交暂存区 git commit -am 'new'  : 将修改过的文件进行记录 git push origin dev : 将项目推送到dev分只 ...