简单剖析AJAX跨域问题

134 阅读2分钟

AJAX是一种技术,是对Asynchronous JavaScript + XML的简写。

异步传输+JS+XML,XML只是一种数据格式,但AJAX通信与数据格式无关,这种技术就是无需刷新页面即可从服务器取得数据,不一定是XML数据,现在大部分用JSON数据。

AJAX的技术核心是XMLHTTPRequest对象,简称XHR。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器获取更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据,从而带来更好的用户体验。

AJAX跨域问题

No 'Access-Control-Allow-Origin' header is present on the requested resource.

前端调用后台接口的时候,如果这个接口不是同一个域的,就会产生跨域问题。

function get1() {
  $.getJSON('http://localhost:8080/test/get1').then(
  function(result) {
    console.log(result)
  })
}

后台接口地址:http://localhost:8080/test/get1

前端运行地址:http://localhost:8081

产生跨域问题的原因

  • 浏览器限制
  • 跨域:发出的请求不是本地的,协议、域名、端口任何一个不一样,浏览器就认为是跨域
  • XHR:默认情况下,XMLHttpRequest对象只能访问与包含它的页面位于同一个域中的资源。这种安全策略可以预防某种恶意行为。

解决跨域的思路和方法

思路一:浏览器

方法:浏览器禁止检查

--disable-web-security --user-data-dir

弊端:需要客户端对浏览器进行修改,价值不大。

思路二:XHR

方法:JSONP

JSONP:JSON with padding 填充式JSON,是被包含在函数调用中的JSON,是应用JSON的一种新方法。

动态创建一个script,利用script标签请求资源可以跨域,来解决跨域问题。

$.ajax({
  url:base+'/get1',
  dataType: 'jsonp',
  jsonp: 'callback', // jsonp的约定,默认是callback
  success: function(json) {
    result = json
  }
})

使用JSONP,服务器后台需要改动,因为JSONP返回的是js代码,不是JSON对象。

JSONP实现原理:

  1. 普通的AJAX发送的请求类型(type)是xhr,JSONP发送的请求type是script
  2. 普通的AJAX返回的类型(Content-Type)是JSON对象,JSONP返回的类型是JS脚本
  3. JSONP发送的时候加了一个callback参数,后台发现有callback参数,就知道这是JSONP请求,就会把返回的数据由JSON变成JS

弊端:

  • 服务器需要改动代码支持
  • 只支持GET方法
  • 发送的不是XHR请求

思路三:跨域

  • 修改被调用方(支持跨域):让被调用方支持跨域,在返回头上增加一些字段,告诉浏览器允许对方调用,支持http协议关于跨域方面的要求,跨域请求直接从浏览器发送出去
  • 修改调用方(隐藏跨域):通过一个代理,从浏览器发出去的都是a域名的请求,在代理中把指定的url转到b域名,这样在浏览器看来,它就是同一个域名,跨域请求通过http服务器转发出去

修改被调用方的支持跨域主要是后台的修改,这里就不赘述了。

调用方解决跨域(隐藏跨域)方法:
  • NGINX反向代理
server {
  listen 80;
  server_name a.com;
  location / {
    proxy_pass http://localhost:8081/;
  }
  location /ajaxserver {
    proxy_pass http://localhost:8080/test/;
  }
}

// 请求的接口的前缀
var base = '/ajaxserver'
  • APACHE反向代理

内容大部分来源视频课程笔记,参见:ajax跨域完全讲解