ajax请求总是不成功?浏览器的同源策略和跨域问题详解
场景
码农小明要做一个展示业务数据的大屏给老板看,里面包含了来自自己网站的数据和来自隔壁老王的数据。
那么自己网站的数据提供了 http://xiaoming.com/whoami 这样的数据接口
隔壁老王提供了 http://oldwang.com/isdad 这样的数据接口
单独点开都是没有问题的。但是一使用 js 的 ajax 请求就无法收到来自 oldwang.com 的数据了。
点开浏览器控制台一看,红字标出(Chrome):
XMLHttpRequest cannot load http://oldwang.com/isdad. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://xiaoming.com/' is therefore not allowed access.
这就是遇到了跨域问题
为什么会有这样的问题?
想象一下如果隔壁老王根本不认识你,他的网站自己有各种用户接口、订单接口、文章接口,那么谁都可以把这些接口返回的数据直接放在自己的网站上了,还是实时的。
所以浏览器制定了一个 同源策略 ,限制了从一个源(origin)中的脚本获取来自其他源(origin)中的资源。
什么是同源
如果两个页面拥有相同的协议(protocol: http),端口(port: 80),和主机(host: xiaoming.com),那么这两个页面就属于同一个源(origin)。
解决方案
这里就不讲多年前的iframe、flash等方式了,只讲几个最常用到的方案
A.x.com 和 B.x.com 间的跨域
子域名不同也是会受到跨域限制的。这种问题最简单,只需要将页面声明为更高级的域就可以了。
<script>
document.domain = "x.com";
</script>
最经典、高效、浏览器兼容最好的解决方案:JSONP
看到JSONP这个名字很多人以为这是和JSON密切相关的一种用来跨域的黑科技,但实际上从跨域的视角看,跟JSON并没有一毛钱关系,他是利用了浏览器允许跨域加载 js 等资源来获取数据。
因为浏览器支持跨域加载 js 如 <script src="http://aliyun.com/....."></script> ,所以很简单,可以把数据包装成 js 就可以了。
这是数据,通过 script 加载到数据无法“执行”,更无法传给 ajax 的回调函数:
{
"data": 123
}
这是js脚本,只要将 callback 与 ajax 的回调函数做关联,就可以讲数据传给回调函数:
callback({
"data": 123
})
这可以看到两点:
一、需要 callback 与 ajax 回调函数绑定;
二、需要数据服务器 配合 的。
三、只支持GET请求
前端如果用 jquery,jquery已经完成了整个取值过程的封装,逻辑是:
1. 随机生成不重复的 callback 函数名,并与 ajax 回调函数 绑定。
1. 将 callback 函数名放入 URL 的 query string 中,如http://oldwang.com/api?callback= jQuery214015557975923291245_1460532274390
1. 生成一个 <script> 标签,将上述 URL 作为 src
1. 等待数据加载,并把数据传入 ajax 的回调函数
后端以 php 为例,逻辑是获取浏览器传来一个参数作为callback包装数据:
<?php
echo $_GET['callback']."(". $data .")";
?>
大部分新浏览器都兼容的 CORS(Cross Origin Resource Sharing)
他的原理是隔壁老王主动告诉浏览器“别拦着小明,我们是亲戚……”
所以最简单的例子,就是在数据服务器返回的头信息中包含:
Access-Control-Allow-Origin: http://xiaming.com
然而这个头信息并不支持枚举,那如果隔壁老王的亲戚太多就只能通过程序来动态得生成这个头信息了,以PHP为例:
<?php
if (is_my_bastard($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
}
?>
如果老王作为一个好人,来者不拒。那么可以直接使用 *
Access-Control-Allow-Origin: *
Cookies
CORS默认是不带 cookie 信息的,如果要带上 cookie 需要添加 withCredentials 参数,以 jquery 为例:
$.ajax({
url: "http://laowang.com/isdad",
xhrFields: {
withCredentials: true
}
});
而服务器还需要加上允许 Credentials 的头信息以及不允许用通配符“*”,如下面的代码
<?php
if (is_my_bastard($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); // 不允许用 *
Access-Control-Allow-Credentials:true
}
?>
ajax请求总是不成功?浏览器的同源策略和跨域问题详解的更多相关文章
- 第二百七十四节,同源策略和跨域Ajax
同源策略和跨域Ajax 什么是同源策略 尽管浏览器的安全措施多种多样,但是要想黑掉一个Web应用,只要在浏览器的多种安全措施中找到某种措施的一个漏洞或者绕过一种安全措施的方法即可.浏览器的各种保安措 ...
- cors跨域和jsonp劫持漏洞 和 同源策略和跨域请求解决方案
cors跨域和jsonp劫持漏洞: https://www.toutiao.com/a6759064986984645127/ 同源策略和跨域请求解决方案:https://www.jianshu.co ...
- 11. cookie_session_原生ajax_readyState的值_同源策略_跨域_jsonp的使用
1. cookie 浏览器存储技术.(服务器将少量数据交于浏览器存储管理) 作用: 存储数据, 解决 http 协议无状态问题 工作流程: 浏览器发送请求给服务器,请求登录 服务器返回响应给浏览器,此 ...
- Ajax_同源策略以及跨域问题
Ajax_同源策略 同源策略是浏览器的一种安全策略, 同源指的是:协议.域名.端口.必须完全相同. 违背同源策略就是跨域. 而AJAX是默认遵循同源策略的: 同源说通俗一点呢就是页面跟获取请求的接口是 ...
- JS同源策略和跨域访问
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只 ...
- JS同源策略和跨域问题
同源策略和跨域问题:http://www.cnblogs.com/chaoyuehedy/p/5556557.html 深入浅出JSONP--解决ajax跨域问题:http://www.cnblogs ...
- 浏览器同源策略,跨域请求jsonp
浏览器的同源策略 浏览器安全的基石是"同源政策"(same-origin policy) 含义: 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这 ...
- 用反向代理nginx proxy_pass配置解决ie8 ajax请求被拦截问题 ie8用nginx代理实现跨域请求访问 nginx405正向代理request_uri
最近调PC版网站ie8的兼容性,发现所有ajax请求还没到后端服务器就直接ajax error了 ie8发不出ajax请求,断点调试发现ajax全进入了error,提示“No transport” 我 ...
- 同源、同源策略、跨域问题、django解决方案
什么是同源: URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源. 注意:假如你的网站ip是123.123.123.123,网站的域名是www.abc.com. ...
随机推荐
- 如果使用得当,MySQL 也可以化身 NoSQL
[编者按]随着互联网和移动互联网的发展,各个机构都需要支撑远超过以往的数据.而在这个需求的刺激下,IT 领域出现了大量数据处理技术,其中之一就是 NoSQL .灵活的数据类型,高效的处理能力,让 No ...
- hdu 2112 HDU Today (最短路,字符处理)
题目 题目很简单,只是多了对地名转化为数字的处理,好吧,这我也是参考网上的处理办法,不过大多数的人采用map来处理 注意初始化注意范围,不然会wa!!!(这是我当时wa的原因org) 大家容易忽视的地 ...
- hdu 4111 Alice and Bob 博弈论
这里有2种方法: 方法一:求SG函数 sg[i][j]:i表示1的个数,j表示合并操作的步数. 这共有4种操作: 1.消除一个1: 2.减掉一个1: 3.合并2个1: 4.把1合并到另外不是1中. 代 ...
- 黑马程序员--C#中属性和字段(变量)的区别
---------------------- ASP.Net+Android+IOS开发..Net培训.期待与您交流! ---------------------- 属性为类提供了一种很有用的封装数据 ...
- IOS 开发中判断字符串是否为空字符的方法
NSUInteger是无符号的整型, NSInteger是有符号的整型,在表视图应用中常见 NSUInteger row= [indexPath row];因为这是显示tableViewCell有多少 ...
- Hibernate逍遥游记-第13章 映射实体关联关系-005双向多对多(使用组件类集合\<composite-element>\)
1. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hi ...
- CreateTwoArray
public class CreateTwoArray{ public static void main(String []args){ int[][]arr=new int [2][3]; Syst ...
- JavaScript基础精华02(函数声明,arguments对象,匿名函数,JS面向对象基础)
函数声明 JavaScript中声明函数的方式:(无需声明返回值类型) function add(i1, i2) { return i1 + i2;//如果不写return返回 ...
- PowerDesigner技巧
原文:PowerDesigner技巧 1.PowerDesigner使用MySQL的auto_increment ◇问题描述: PD怎样能使主键id使用MySQL的auto_increment呢? ...
- iOS 精确定时器
Do I need a high precision timer? Don't use a high precision timer unless you really need it. They c ...