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属性是没有跨域的限制的 ...
随机推荐
- UDP Server
//UDP服务器端程序,可以接受广播,不可接受多播,多播需要join播地址@Override public void run() { while (true) { try { DatagramSock ...
- js兼容性
1.getElementByClassName 在使用原生JavaScript时,获取类选择符时,即使用getElementByClassName,它在Firefox和IE下是不能兼容. Firefo ...
- weui dialog
切记:weui dialog 的样式是在weui.css,而不是在weui.min.css HTML: <!DOCTYPE html> <html> <head> ...
- rank()函数的使用
排序: ---rank()over(order by 列名 排序)的结果是不连续的,如果有4个人,其中有3个是并列第1名,那么最后的排序结果结果如:1 1 1 4select scoreid, stu ...
- sql 取汉字首字母
)) ) --用于加密 --WITH ENCRYPTION as begin declare @intLen int ) ) set @intLen = len(@str) set @strRet = ...
- 关系数据库—SQL学习笔记
SQL的特点: 综合统一 高度非过程化(存取路径的选择以及SQL的操作过程由系统自动完成) 面向集合的操作方式,以同一种语法结构提供多种使用方法(可以在终端键盘上直接键入SQL命令对数据库进行操作,也 ...
- ElasticSearch中bulkProcesser使用
初次接触es,可能对增删改查很熟悉,以为能为得心应手,本次应用场景为 数据库变更一条记录,会触发更新es中的数据,每秒并发大概30条左右,测试环境一切工作正常(数据量较少),上线后发现日志中很多类似于 ...
- 说说APP接口中的版本控制
引言 接口是APP的重要组成部分,数据是APP的核心,接口是连接APP和数据的纽带. 一般情况下,APP中会有大量的接口,再加上版本的变化,接口的升级,一个接口 可能会衍生出很多个稍有差异的接口,这个 ...
- JavaScript系列文章:从let和const谈起
注册博客园账号也有好些年了,有事没事经常来逛逛,感觉博客园的同学们一直都很活跃,相比国内其他社区来讲,这里的技术氛围很浓,非常适合学习和交流,所以博主我也决定在这里驻扎了,在这里,博主希望能坚持写一些 ...
- Linux下Steam中支持中文的办法
搜索过好几个解决方案,诸如添加skin等等,在我的ARCH机器上似乎都不行然后在搜索linux steam cjk时, 发现一个链接中有解决DOTA2显示中文不正确的问题,感觉可能有用,就参考着搞定了 ...