为什么会跨域

跨域的原因:浏览器的同源策略(是一种安全策略,用于隔离潜在恶意文件)

浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对Dom的查询。如果没有同源策略,会出现以下的安全问题:

1. 没有同源策略限制的接口请求

CSRF(Cross-site request forgery)攻击,中文名:跨站请求伪造

步骤:
1. 登录受信任网站A,并在本地生成Cookie
2. 在不登出A的情况下,访问危险网站B

2. 没有同源策略限制的Dom查询

利用高仿域名和iframe干坏事

1
2
3
4
5
6
7
// HTML
<iframe name="yinhang" src="www.yinhang.com"></iframe>
// JS
// 由于没有同源策略的限制,钓鱼网站可以直接拿到别的网站的Dom
const iframe = window.frames['yinhang']
const node = iframe.document.getElementById('你输入账号密码的Input')
console.log(`拿到了这个${node},我还拿不到你刚刚输入的账号密码吗`)

解决跨域问题

同源策略一定程度上防止了如CSRF这种恶意攻击,但也给开发造成了一些不便。尤其在流行前后端分离的开发模式之后,前端的开发环境通常会有自己的服务,调用后端端口时由于跨域问题会调用失败,那么我们有以下的方法来解决跨域问题:

  1. JSONP

    在HTML标签里,一些标签比如script、img这样的获取资源的标签是不会受跨域限制,JSONP正是利用了这一点。

  2. 空iframe加form

    JSONP只能发GET请求,因为本质上script标签获取资源就是GET请求,如果想要发送POST请求,可以利用空irame加form的办法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    const requestPost = ({url, data}) => {
    // 首先创建一个用来发送数据的iframe.
    const iframe = document.createElement('iframe')
    iframe.name = 'iframePost'
    iframe.style.display = 'none'
    document.body.appendChild(iframe)
    const form = document.createElement('form')
    const node = document.createElement('input')
    // 注册iframe的load事件处理程序,如果你需要在响应返回时执行一些操作的话.
    iframe.addEventListener('load', function () {
    console.log('post success')
    })

    form.action = url
    // 在指定的iframe中执行form
    form.target = iframe.name
    form.method = 'post'
    for (let name in data) {
    node.name = name
    node.value = data[name].toString()
    form.appendChild(node.cloneNode())
    }
    // 表单元素需要添加到主文档中.
    form.style.display = 'none'
    document.body.appendChild(form)
    form.submit()

    // 表单提交后,就可以删除这个表单,不影响下次的数据发送.
    document.body.removeChild(form)
    }
    // 使用方式
    requestPost({
    url: 'http://localhost:9871/api/iframePost',
    data: {
    msg: 'helloIframePost'
    }
    })
  1. CORS

    CORS(Corss-origin resource sharing)是一个W3C标准,全称是“跨域资源共享”。
    CORS详解

  2. 代理

    服务器之间的通信不存在同源策略问题,例如webpack-dev-server:

    1
    2
    1. browser => localhost:8080(webpack-dev-server无代理) => http://you.test.com
    2. browser => localhost:8080(webpack-dev-server有代理) => http://you.test.com
    • 上面第一种情况客户端直接访问跨域的服务端,会受同源策略限制。
    • 而第二种,客户端访问代理服务器,代理服务器访问真正的服务器。服务器之间的通信不存在同源策略问题,所以同源策略的问题就通过代理服务器得到了解决。