跨域请求方法

跨域

  1. 不同源的Ajax请求均为跨域, 即浏览器url和请求接口地址的协议+域名+端口有一个不相同的Ajax请求
  2. 受浏览器的同源策略影响,浏览器会拒绝不同源的Ajax请求.

同源策略

  • 是浏览器的基本安全策略,不能通过Ajax请求不同域的数据
  • 同源:协议+域名+端口相同
  • 解决:XSS、CSFR等攻击

为什么需要跨域请求

一个需求需要请求多个服务器的接口

跨域请求方式

1. jsonp

使用script标签进行发起get请求,因为script标签请求不受同源策影响,script标签的get请求不是Ajax请求。

  • 优点: 兼容性好
  • 缺点: 只能发起get请求,jsonp的错误处理机制没有XMLHttpRequst好
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
<script src="http://test.com/data.php?callback=dosomething"></script>
 
// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(res){
    console.log(res.data)
}
</script>
// 封装方法
function jsonp({url, params, callback}) {
  jsonp.cbId = jsonp.cbId || 1
  jsonp.callbacks = jsonp.callbacks || []
  jsonp.callbacks[jsonp.cbId] = callback

  let script = document.createElement('script')
  params['callback'] = `jsonp.callbacks[${jsonp.cbId}]`
  script.setAttribute('src', url + getParams(params))
  document.body.append(script)

  jsonp.cbId++
}

// 处理服务器返回回调函数的数据
function dosomething(res){
    console.log(res.data)
}
jsonp({
  url: "http://test.com/data.php?callback=dosomething",
  params: {id: 1},
  callback: dosomething
})

2. CORS 跨域资源共享

CORS 是W3C的一个官方方案,跨源Ajax请求的根本解决方法。

  • 普通跨域实现:服务器端设置Access-Control-Allow-Origin, 如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问
// 服务器
response.setHeader("Access-Control-Allow-Origin", "http://www.main.com"); // 指定地址可以访问 
response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有域访问
  • 带cookie的跨域请求:前端需设置xhr.withCredentials = true,服务器端设置Access-Control-Allow-Origin
// 前端
let xhr = new XMLHttpRequest()
xhr.withCredentials = true // 前端设置是否带cookie

// 服务器
response.setHeader("Access-Control-Allow-Origin", "http://www.main.com"); 
response.setHeader("Access-Control-Allow-Credentials", "true");

3. postMessage

window.postMessage(mssage, targetOrigin) 是html5新引进的特性,可以用来向其他window对象发送消息,无论这个window对象属于同源或不同源。

window.postMessage(message, targetOrigin);
const openWindow = window.open('http://www.test.com', 'title')
openWindow.postMessage('the data', 'http://www.test.com')

// http://www.test.com 接受消息
window.addEventListener('message', function(e) {
  console.log(e.data) // 发送的数据
  console.log(e.source) // 消息发送的地址
  console.log(e.origin) // 消息发向的地址
})
上一篇:Gecco抓取实例


下一篇:jQuery ajax中支持的数据类型