抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

前言

最近在做项目,当我将项目丢到生产环境给前端使用接口时,出现了跨域问题,很难受发现一如既往的CrossOrigin不好使了,同时也发现自己对跨域没有了解过,因此今天就来学习一下拉。

跨域

什么是跨域

当一个请求URL的协议、域名(IP地址)、端口三者之间任意一个与当前URL不同就为跨域。

ps:(跨域是浏览器正确做出请求,服务器也能正确做出响应,是浏览器拒绝接收跨域服务器返回的数据;)

当前请求页面URL 被请求页面URL 是否跨域 跨域原因
http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 协议不同(http/https)
http://www.test.com/ http://www.baidu.com/ 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 端口号不同(8080/7001)

为什么会出现跨域问题

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。

非同源的限制

  1. 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  2. 无法接触非同源网页的 DOM
  3. 无法向非同源地址发送 AJAX 请求

如何解决跨域的问题

同域代理

用域代理就是向同域下的后台服务器发送请求、同时携带真实的请求和地址以及参数,后台接受请求后直接根据地址及参数转发请求,因为后台是可以直接模拟HTTP客户端发送请求的,所以没有跨域问题,而后台接受到响应数据后再原样返回给前端浏览器,从而实现跨域数据交互。(跨域问题只出现在浏览器中,这种方法就是绕过了浏览器

JSONP

JSONP是利用了 script 标签的 src 属性来实现跨域数据交互的,因为浏览器解析HTML代码时,原生具有src属性的标签,浏览器都赋予其HTTP请求的能力,而且不受跨域限制,使用src发送HTTP请求,服务器直接返回一段JS代码的函数调用,将服务器数据放在函数实参中,前端提前写好响应的函数准备回调,接收数据,实现跨域数据交互。(要注意JSONP只支持GET请求,不支持POST请求

CORS

CORS跨域资源共享(Cross-Origin resource sharing),得益于HTTP/1.1版本中添加的许多头部字段,使得浏览器可以通过HTTP头部字段来分辨,这些请求头有两个作用

1. 用于阻止还是允许浏览器向其他域名发起请求;
2. 用于接受还是拒绝其他域名返回的响应数据;

当浏览器发送请求时发现是跨域请求的话,就会添加上Origin请求头,用来标识请求来自于哪一个站点。当服务端允许本次响应消息可以被共享的话,就要添加一个Access-Control-Allow-Origin响应体指名可以共享数据的域。当值为*时代表可以与任意域进行数据共享。

在CORS中所有跨域请求被分为两个类型、一个是简单请求、一种是复杂请求。简单请求与普通的ajax请求无异;但复杂请求,必须在正式发送请求前先发送一个OPTIONS方法的请求已得到服务器的同意,若没有得到服务器的同意,浏览器不会发送正式请求;

满足以下所有条件,被视为简单类型的请求:

  1. 请求方法必须是 GET、HEAD、POST中的一种,其他方法不行;
  2. 请求头类型只能是 Accept、Accept-Language、Content-Language、Content-Type,添加其他额外请求头不行;
  3. 请求头 Content-Type 如果有,值只能是 text/plain、multipart/form-data、application/x-www-form-urlencoded 中的一种,其他值不行;
  4. 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;
  5. 请求中没有使用 ReadableStream 对象。

而以上的条件有任意一条不满足,则视为复杂类型的请求

跨域CORS头部字段

CORS头信息 说明
Access-Control-Allow-Origin(响应) 指示请求的资源能共享给哪些域,可以是具体的域名或者*表示所有域。
Access-Control-Allow-Credentials(响应) 指示当请求的凭证标记为 true 时 是否响应该请求。
Access-Control-Allow-Headers(响应) 用在对预请求的响应中,指示实际的请求中可以使用哪些 HTTP 头。
Access-Control-Allow-Methods (响应) 指定对预请求的响应中, 哪些 HTTP 方法允许访问请求的资源。
Access-Control-Request-Headers (请求) 用于发起一个预请求,告知服务器正式请求会使用那些 HTTP 头。
Access-Control-Request-Method (请求) 用于发起一个预请求,告知服务器正式请求会使用哪一种 HTTP 请求方法。
Origin(请求) 指示获取资源的请求是从什么域发起的