文档章节

ajax请求总是不成功?浏览器的同源策略和跨域问题详解

乱蓬头
 乱蓬头
发布于 2017/07/12 14:30
字数 1107
阅读 4
收藏 0

摘要: XMLHttpRequest cannot load http://oldwang.com/isdad. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://xiao

场景

码农小明要做一个展示业务数据的大屏给老板看,里面包含了来自自己网站的数据和来自隔壁老王的数据。
那么自己网站的数据提供了 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

但是有一个致命的缺点:非常高的跨站脚本攻击风险,所以 DataV 是不支持这种方式的

看到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']}"); // 不允许用 *
  header("Access-Control-Allow-Credentials:true");
}
?>

这就是隔壁老王的故事

本文转载自:http://click.aliyun.com/m/25768/

乱蓬头
粉丝 0
博文 382
码字总数 2595
作品 0
私信 提问
出现跨域问题的原因及其解决方法

出现跨域问题的原因: 同源策略 同源策略 三同 协议相同 域名相同 端口相同 同源策略目的 保证用户信息安全,防止恶意网站窃取数据。同源策略是必须的,否则cookie可以共享。 同源策略的限制...

Husbin
2018/01/11
0
0
前端筑基篇(一)->ajax跨域原理以及解决方案

说明 本文内容较老,而且已经不再更新,最新更新请移步 http://www.jianshu.com/p/82b82d5dd1ea 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 ...

撒网要见鱼
2016/09/21
0
0
浏览器同源策略及 Ajax 跨域解决方案

因为在开发过程中会经常遇到因为浏览器同源策略而导致的跨域问题,而多数开发者对浏览器同源策略和跨域问题并没有很清晰的认识,所以打算在这篇文章中说下浏览器同源策略和我们最经常会遇到的...

淘淘笙悦
2018/07/13
0
0
ajax跨域问题

当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域 Access-Control-Allow-Origin解决Ajax跨域问题// 指定可信任的域名...

ITCHN
2016/12/22
15
0
详解js跨域问题

什么是跨域? 概念:只要协议、域名、端口有任何一个不同,都被当作是不同的域。 URL 说明 是否允许通信http://www.a.com/a.jshttp://www.a.com/b.js 同一域名下 允许http://www.a.com/lab/...

wecloudnet
2016/04/08
190
0

没有更多内容

加载失败,请刷新页面

加载更多

nproc systemd on CentOS 7

Increasing nproc for processes launched by systemd on CentOS 7 Ask Question I have successfully increased the nofile and nproc value for the local users, but I couldn't find a p......

MtrS
今天
3
0
了解微信小程序下拉刷新功能

小程序提供了这个事件。 onPullDownRefresh() 监听用户下拉刷新事件。 如果要开启下拉刷新功能,要先到json配置: "enablePullDownRefresh":true 配置后下拉有反应了但是没有加载效果,在onP...

oixxan__
今天
2
0
springmvc java对象转json,上传下载(未完)拦截器Interceptor以及源码解析(未完待续)

package com.atguigu.my.controller;import java.util.Collection;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Contr......

architect刘源源
今天
29
0
[日更-2019.5.24、25、26] Android系统中的Binder通信机制分析(一)--servicemanager

声明 其实对于Android系统Binder通信的机制早就有分析的想法,记得去年6、7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾... 最近,刚好在做...

Captain_小馬佩德罗
昨天
24
0
聊聊dubbo的DataStore

序 本文主要研究一下dubbo的DataStore DataStore dubbo-2.7.2/dubbo-common/src/main/java/org/apache/dubbo/common/store/DataStore.java @SPI("simple")public interface DataStore { ......

go4it
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部