前端学习日志 —— 跨域问题学习总结

4 阅读4分钟

一、什么是跨域

在浏览器中,存在一种安全机制叫做 同源策略(Same-Origin Policy)
同源策略规定:

一个网页的脚本只能访问与该网页 同源 的资源。

所谓 同源(Origin) 指的是:

协议 + 域名 + 端口

三者必须 完全一致 才算同源。

例如:

页面地址请求地址是否同源
a.coma.com/api
a.coma.com/api否(协议不同)
a.comb.com/api否(域名不同)
a.com:3000a.com:4000否(端口不同)

只要 协议、域名、端口有一个不同,就属于 不同源请求(跨源请求)

当浏览器阻止这种请求时,就产生了我们常说的 跨域问题


二、为什么浏览器要限制跨域

浏览器限制跨域主要是为了 安全原因,防止恶意网站窃取用户信息。

例如:

用户登录了

bank.com

浏览器中已经保存了登录 Cookie。

如果没有同源策略,用户访问恶意网站:

hack.com

hack.com 就可以执行:

fetch("https://bank.com/api/userinfo")

从而获取用户的:

  • 银行账户
  • 余额
  • 交易记录

这会造成严重的信息泄露问题。

因此浏览器规定:

一个网站的 JavaScript 不能随意读取另一个网站的数据。

这就是同源策略存在的原因。


三、跨域什么时候会出现

跨域通常出现在 前端请求后端接口时

例如在开发环境中:

前端运行在:

http://localhost:8081

后端接口运行在:

http://localhost:8080

两者比较:

项目前端后端
协议httphttp
域名localhostlocalhost
端口80818080

由于 端口不同,所以属于 不同源请求

当使用 AJAX 请求接口时:

axios.get("http://localhost:8080/api/user")

浏览器会认为这是 跨域请求

如果服务器没有返回 CORS 允许信息,浏览器就会报跨域错误。


四、跨域请求不一定都会被拦截

需要注意的是:

不同源请求 ≠ 一定报跨域

浏览器实际上允许 某些资源跨域加载

例如:

<img>
<script>
<link>
<video>
<audio>

例如:

<img src="http://other.com/a.png">

这是跨域请求,但浏览器允许加载。

原因是:

这些资源只能被加载,但 JavaScript 无法读取返回的数据。

因此安全风险较小。


五、为什么图片可以跨域加载,而 AJAX 不可以

浏览器对跨域请求做了一个重要区分:

1 资源加载(允许)

例如:

<img>
<script>
<link>

特点:

  • 可以跨域加载
  • JavaScript 无法读取返回的数据

例如图片:

<img src="http://b.com/a.png">

JS 无法获取图片的真实内容数据。

因此浏览器认为风险较小。


2 数据读取(限制)

AJAX 属于 数据读取行为

fetch("http://b.com/api/user")

特点:

  • JS 可以直接获取返回数据
  • 数据可能包含敏感信息

例如:

用户信息
银行余额
订单数据

因此浏览器默认禁止这种跨域访问。

只有当服务器明确允许时,浏览器才会放行。

服务器需要返回:

Access-Control-Allow-Origin

例如:

Access-Control-Allow-Origin: http://a.com

这就是 CORS(跨域资源共享)机制


六、JSONP 技术

在 CORS 出现之前,前端常用 JSONP 技术解决跨域问题。

JSONP 的核心思想是:

利用 <script> 标签可以跨域加载资源的特点来获取数据。

因为 <script> 标签不受同源策略限制。


1 JSONP 的实现原理

JSONP 的流程如下:

第一步:前端定义回调函数

function callback(data){
    console.log(data)
}

第二步:动态创建 script 标签

const script = document.createElement("script")

script.src = "http://api.com/user?callback=callback"

document.body.appendChild(script)

浏览器会请求:

http://api.com/user?callback=callback

第三步:服务器返回 JS 代码

服务器返回的不是 JSON,而是:

callback({
  "name":"Tom",
  "age":20
})

第四步:浏览器执行代码

浏览器加载 script 后,会执行:

callback({
  "name":"Tom",
  "age":20
})

从而调用前端函数,得到数据。


七、JSONP 的优缺点

优点

  • 可以解决跨域问题
  • 实现方式简单

缺点

1 只支持 GET 请求

因为 <script> 只能使用 GET。

不能发送:

POST
PUT
DELETE

2 存在安全问题

服务器返回的是 JavaScript 代码

如果服务器被攻击,可能返回恶意代码:

alert("恶意代码")

浏览器会直接执行。


3 错误处理困难

AJAX 可以处理:

status
error
timeout

JSONP 很难实现这些功能。


八、现代解决跨域的方式

目前主流解决跨域的方法是 CORS

服务器只需要返回:

Access-Control-Allow-Origin

例如:

Access-Control-Allow-Origin: *

或者:

Access-Control-Allow-Origin: http://localhost:8081

这样浏览器就允许前端访问接口。


九、总结

本次学习主要理解了 跨域产生的原因以及解决方式

核心知识点如下:

  1. 浏览器存在 同源策略
  2. 同源由 协议 + 域名 + 端口 共同决定。
  3. 只要其中一个不同,就属于 跨源请求
  4. 浏览器允许 跨域加载资源,但不允许 跨域读取数据
  5. AJAX 属于数据读取,因此会被限制。
  6. JSONP 通过 <script> 标签跨域加载实现数据获取,但只支持 GET。
  7. 现代开发通常使用 CORS 解决跨域问题。