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. UDP Server

    //UDP服务器端程序,可以接受广播,不可接受多播,多播需要join播地址@Override public void run() { while (true) { try { DatagramSock ...

  2. js兼容性

    1.getElementByClassName 在使用原生JavaScript时,获取类选择符时,即使用getElementByClassName,它在Firefox和IE下是不能兼容. Firefo ...

  3. weui dialog

    切记:weui dialog 的样式是在weui.css,而不是在weui.min.css HTML: <!DOCTYPE html> <html> <head> ...

  4. rank()函数的使用

    排序: ---rank()over(order by 列名 排序)的结果是不连续的,如果有4个人,其中有3个是并列第1名,那么最后的排序结果结果如:1 1 1 4select scoreid, stu ...

  5. sql 取汉字首字母

    )) ) --用于加密 --WITH ENCRYPTION as begin declare @intLen int ) ) set @intLen = len(@str) set @strRet = ...

  6. 关系数据库—SQL学习笔记

    SQL的特点: 综合统一 高度非过程化(存取路径的选择以及SQL的操作过程由系统自动完成) 面向集合的操作方式,以同一种语法结构提供多种使用方法(可以在终端键盘上直接键入SQL命令对数据库进行操作,也 ...

  7. ElasticSearch中bulkProcesser使用

    初次接触es,可能对增删改查很熟悉,以为能为得心应手,本次应用场景为 数据库变更一条记录,会触发更新es中的数据,每秒并发大概30条左右,测试环境一切工作正常(数据量较少),上线后发现日志中很多类似于 ...

  8. 说说APP接口中的版本控制

    引言 接口是APP的重要组成部分,数据是APP的核心,接口是连接APP和数据的纽带. 一般情况下,APP中会有大量的接口,再加上版本的变化,接口的升级,一个接口 可能会衍生出很多个稍有差异的接口,这个 ...

  9. JavaScript系列文章:从let和const谈起

    注册博客园账号也有好些年了,有事没事经常来逛逛,感觉博客园的同学们一直都很活跃,相比国内其他社区来讲,这里的技术氛围很浓,非常适合学习和交流,所以博主我也决定在这里驻扎了,在这里,博主希望能坚持写一些 ...

  10. Linux下Steam中支持中文的办法

    搜索过好几个解决方案,诸如添加skin等等,在我的ARCH机器上似乎都不行然后在搜索linux steam cjk时, 发现一个链接中有解决DOTA2显示中文不正确的问题,感觉可能有用,就参考着搞定了 ...