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. visual studio 2013 使用域名调试本地项目

    一.在localhost添加需要指定的域名,如:test.domain.com 二.以管理员身份启动VS,并打开项目 三.修改IIS Express的配置文件(一般位于:C:\Users\当前用户\D ...

  2. VB6史无前例的子类化之透明按钮

    [原创文章,转发请保留版权信息] 作者:mezstd 文章地址:http://www.cnblogs.com/imez/p/3299728.html 效果图: 请原谅笔者无耻地称之为史无前例,至少在笔 ...

  3. Android环境变量配置

    第一步: 把这些东西全部准备好!然后jdk怎么安装我相信大家都知道.安装好jdk之后,我们来配置环境变量. 我的电脑—右键—属性—高级系统设置—环境变量 JAVA_HOME环境变量.它指向jdk的安装 ...

  4. android获取位置location为null的问题

      12:38:542016-12-23 很多人经常遇到这种问题,主要是获取到位置的信息为null,第一个主要要有权限 <uses-permission android:name="a ...

  5. Web Application Penetration Testing Local File Inclusion (LFI) Testing Techniques

    Web Application Penetration Testing Local File Inclusion (LFI) Testing Techniques Jan 04, 2017, Vers ...

  6. 【总结】富有表现力的JavaScript

    1.JavaScript的灵活性 JavaScript是目前最流行.应用最广泛的语言之一,它是一种极富表现力的语言,它具有C家族语言所罕见的特性.这种语言允许我们使用各种方式来完成同一个任务或者功能, ...

  7. ubuntu修改163软件源

    cd /etc/apt cat sources.list sudo su root sudo echo '' > sources.list nano sources.list 复制163软件源 ...

  8. BZOJ3879: SvT

    后缀数组裸题,每次的查询单调栈扫一遍就完了.为什么要写虚后缀树= =后缀数组不是自带虚树的结构么= = #include<cstdio> #include<algorithm> ...

  9. v-for遍历出的元素上添加click事件,获取对应元素上的属性id值

    <span v-for="(n,nav) in floorList" data-id="{{nav.itemId}}" v-on:click=" ...

  10. 【转载】如何用IntelliJ IDEA 14 创建Web项目

    首先要理解一个概念:在IntelliJ IDEA中"new Project"相当于eclipse中的工作空间(Workspace),而"new Module"相 ...