# 跨域及解决方案

# 什么是同源策略

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

# 同源策略限制内容

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求发送后,结果被浏览器拦截了

但是有三个标签是允许跨域加载资源:

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

# 跨域解决方案

// 1.原生 node 实现
app.use(async (ctx, next) => {
  ctx.set('Access-Control-Allow-Origin', ctx.headers.origin)
  ctx.set('Access-Control-Allow-Credentials', true)
  ctx.set('Access-Control-Request-Method', 'PUT,POST,GET,DELETE,OPTIONS')
  ctx.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, cc')
  if (ctx.method === 'OPTIONS') {
    ctx.status = 204
    return
  }
  await next()
})
1
2
3
4
5
6
7
8
9
10
11
12
// 2.使用第三方中间件
/**
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。
**/
const cors = require('koa-cors')
app.use(cors())

// 3.使用 node 正向代理,比如
webpackConfig.devServer.proxy

// 4.使用 nginx 反向代理
// 实现原理类似于Node中间件代理,需要你搭建一个中转nginx服务器,用于转发请求。

// 5.websocket
// WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据

// 6.iframe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 5.jsonp
// 利用 script 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。
// JSONP请求一定需要对方的服务器做支持才可以。
<script>
  window.jsonpCallback = function(res) {
    console.log(res)
  }
</script>
<script
  src="http://localhost:8080/api/jsonp?msg=hello&cb=jsonpCallback"
  type="text/javascript"
></script>
<script>
  jsonpCallback({ a: 1 })
</script>

// 6.window.postMessage // index.html
// postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
<iframe src="http://localhost:8080" frameborder="0" id="iframe" onload="load()"></iframe>
<script>
  function load() {
    iframe.contentWindow.postMessage('秋风的笔记', 'http://localhost:8080')
    window.onmessage = e => {
      console.log(e.data)
    }
  }
</script>
// another.html
<div>hello</div>
<script>
  window.onmessage = e => {
    console.log(e.data) // 秋风的笔记
    e.source.postMessage(e.data, e.origin)
  }
</script>
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

在线客服