# 什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
An image

  • 浏览器的同源策略:这是一种约定,它会组织一个域的javascript脚本和另一个域的内容进行交互。

  • 同源就是指在同一个域下,两个页面具有相同的协议、主机和端口号

非同源限制

  • 无法读取非同源网页的Cookie、LocalStorage和IndexedDB
  • 无法解除非同源网页的dom
  • 无法向非同源地址发送ajax请求

# 跨域解决方法

# 1.设置document.domain

//两个页面都需要设置
document.domain = "test.com"
  • 因为浏览器是通过document.domain属性来检测两个页面是否同源,因此将两个页面都设置相同的document.domain, 两个页面就可以共享cookie,需要注意的是此方法仅限 主域相同,子域不同 的跨域应用场景

# 2.window.postMessage(),跨文档通信API

  • 调用postMessage方法可以实现父窗口http://test1.com向子窗口http://test2.com发消息, 子窗口也可以调用该方法发消息给父窗口
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title')
// 父窗口向子窗口发消息(第一个参数是内容,第二个参数是收消息窗口的url)
openWindow.postMessage('test1 call test2', 'http://test2.com')

// 调用message事件来监听对方发送的消息
window.addEventListener('message', function(e) {
  console.log(e.source, e.origin, e.data)
  // e.source 发送消息的窗口   e.origin 消息发向的网址   e.data 发送的消息内容
})

它可以用于解决以下问题:

  • 页面与其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套iframe消息传递
  • 以上场景的跨域数据传递

# 3.JSONP

JSONP是服务器与客户端跨域源通信的常用方法,简单实用,兼容性好,但是**只支持get请求**,不支持post请求

主要实现方式是网页通过添加一个<script>元素,向服务器请求JSON数据,服务器收到请求后, 将数据放在一个指定名字的回调函数的参数位置传回来

  • 原生实现
<script src="http://abc.com:8080/user.php?callback=somebody"></script>
// 向服务器发出轻轻,该请求的查询字符串有一个callback参数,用来指定回调函数的名字

// 处理服务器返回回调函数的数据  
<script type="text/javascript">0
  function somebody(res) {
    console.log(res)  //处理获得的数据
  }
</script>

# 4.CORS

CORS是跨域分享(Cross-Origin Resource Sharing)的缩写,它是W3C标准,属于跨源ajax请求的根本解决方法

普通跨域请求: 只需要服务端设置Access-Control-Allow-Origin

带cookie跨域请求: 前后端都需要进行设置

前端设置: 根据xhr.withCredentials字段判断是否带有cookie

  • 原生ajax情况下:
var xhr = new XMLHttpRequest()
xhr.withCredentials = true

xhr.open('post', 'url', true)
...
  • jQuery ajax
$.ajax({
  url: 'www.abc.com:8080/user',
  type: 'get',
  data: {},
  xhrFields: {
    withCredentials: true   // 是否携带cookie
  },
  crossDomain: true     // 请求头携带额外的跨域信息,但不包含cookie
})
  • vue-resource
Vue.http.options.credential = true
  • axios
axios.defaults.withCredentials = true

服务端设置: 设置Acess-Control-Allow-Origin来允许ajax进行跨域访问