同源与跨域问题
同源策略: 为了阻止cookie在不同的网站之间传输
同源: 协议相同, 域名相同, 端口号相同
两个页面的上面三点都相同, 才是同一个网站, 就是同源
http协议的端口号默认是80, 可省
http: // www.baidu.com [:80] /dir/index.html
协议 域名 80端口,可省
跨域问题的产生:
我们写的前端代码是放在一台网页服务器中的, 公司中接口数据是放在另一台数据服务器中的,
我们在我们这台服务器中访问接口数据就会产生跨域
(PS 为什么会产生跨域:
因为两台服务器在互联网中的域名一定是不一样的 -->每台计算机在网络中都有一个唯一的ip标识.
域名不一样的, 所以一定会跨域)
比方说我们前端代码部署在前端服务器中, 前端html页面的地址是
http://www.dilireba.com/index.html
我们在这个index.html中发送ajax请求, 请求地址是另一台服务器中的地址
http://www.ahhhh.com/data.json
那么因为域名不同, 所以这两个页面不是属于同一个网站, 造成跨域
所以ajax获取不到数据
我们现在每次开发时, 代码都是放到本地服务器中的, 所以是同一个服务器, 所以一直没有跨域情况产生
jsonp解决跨域问题 --> jsonp的演变
原理:
服务器端返回一个函数fn(实参), 这个函数一定是带参数的,前端调用这个函数fn(形参), 这样后台就把数据传过来了
原理的原理:
script可以请求跨域的文件内容, 并将文件内容当成js代码执行
比方说我们在后台的http://www.baidu.com/json.php文件中写上
<?php echo “alert(666)”?>
然后在本地服务器中的http://localhost.index.html中引入
<script src=” http://www.baidu.com/json.php”></script>
这样打开index.html文件, 就可以跨域请求到(访问到)不是同源网站的json.php文件, 并将文件中的代码当成js代码执行, 就这样我们就得到服务器中的数据了
(这里虽然是php文件, 但是我们访问这个php页面时, 因为服务器会先运行自己的php文件中的代码, 将结果返回给浏览器, 所以我们访问这个php文件时, 得到的是alert(666)这个js代码)
那么我们在json.php中echo ”var a = ‘data’”
然后在index.html中console.log(a) 就会打印出data, 实现后台数据跨域拿到前台(隐藏点是script引入的js代码就是当前页面中写的js代码了)
优化方法是:
在index.html中定义一个全局方法
function fn(data) { console.log(data)}
然后我们后台的json.php中echo “fn(我们想要返回的数据)”
这样我们在前台调用这个函数的时候, 就能打印出我们想要后端的数据了
这个函数起名字是前端起的, 但是“假”调用时在后端, 真调用还是在前端
但是这里还有一个缺点: 后台得根据前端的这个函数名提前写死
优化是:
在我们的script中传入参数
前端中的这个全局函数名还是得先定下来, 比方叫fn
那么<script src=” http://www.baidu.com/json.php?callback=fn”></script>
php.son文件中 $callback = $_GET[callback] echo “$callback(‘要传输的数据’)”
上面的是jsonp的优化过程, 实际用起来不方便, jquery将jsonp封装到了ajax方法中
$.ajax({
datatype: ‘jsonp’ 之前默认不写是json类型, 现在需要跨域, 所以告诉ajax一声
})
cors解决跨域问题
cross origin resource sharing 跨域资源共享
要求: 浏览器ie10+, 服务器允许跨域
如果公司使用流行框架开发项目的话, 那么就不用考虑兼容问题了, 因为至少ie9+才可以使用流行框架
跨域行为造成浏览器中不能拿到数据的原理:
这是浏览器自己造成的, 无论你跨不跨域, 只要你访问服务器, 服务器都会给在响应中给你返回数据, 但是浏览器会自己判断自己有没有做相应的设置, 如果没有, 就会自动忽略不同源的网站的响应, 报跨域的错误.
jsonp对比cors
jsonp没有兼容问题, 但是只支持get请求, 所以数据大小有限制
cors必须浏览器ie10+, 支持所有请求, 数据大小没有限制
但是两者都需要服务器进行允许跨域的设置, 光凭前端没法跨域, 所以我们前端很快乐啊, 啥都不用做, 就是告诉后台,得跨域!
跨域问题的终极解决方式 -->反向代理
反向代理也能解决跨域问题, 并且是the most fuking awesome的解决跨域方式, 没有兼容问题, 大小限制
在服务器中进行相应配置, 前端不需要访问api.json这个不同源的页面, 正常访问网页服务器中的某个页面, 网页服务器就会自动将你这个请求, 通过它自己的设置代理访问数据服务器中的接口, 拿回数据, 然后再通过网页服务器返回给你, 就好像你是在网页服务器中拿数据一样
同样, 前端啥也不用做,啊哈哈哈...