Js跨域方法

Posted by BY CHUGAO on December 12, 2020

JS - 这些跨域方法,你都知道吗?

跨域

协议、域名、端口不同,需要跨域

跨域解决方案

jsonp:JSON with Padding

  • script 标签没有同域限制
  • 服务端返回页面上 callback 包裹的 json 数据
  • 兼容性好
  • 仅支持 GET

    CORS:Cross-origin resource sharing 跨域资源共享

    简单请求 :

    满足以下 2 条件

  • GET HEAD POST
  • Content-Type
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

      复杂请求:

      不满足以上2条件

  • 需发送 OPTION 预检请求,查询服务器支持的方法
  • 按请求类别处理 ```js const express = require(‘express’) const app = express() const whiteList = [‘http://localhost’] app.use((req, res, next) => { const origin = req.headers.origin if (whiteList.includes(origin)) { // 允许访问源,附带凭证请求时,必须指定 URI。相反,可设置为 * res.setHeader(‘Access-Control-Allow-Origin’, origin) // 允许请求头,逗号隔开 res.setHeader(‘Access-Control-Allow-Headers’, ‘authorization, username’) // 允许请求方法,逗号隔开 res.setHeader(‘Access-Control-Allow-Methods’, ‘GET, HEAD, POST, OPTIONS’) /* 允许凭证 客户端需配置 const xhr = new XMLHttpRequest() xhr.withCredentials = true */ res.setHeader(‘Access-Control-Allow-Credentials’, true) // 预检请求的返回结果,允许请求头和请求方法可以被缓存多久,缓存期间不再发送预检请求,单位秒 res.setHeader(‘Access-Control-Allow-Max-Age’, 10) // 允许响应头 res.setHeader(‘Access-Control-Expose-Headers’, ‘authorization, username’) if (req.method === ‘OPTIONS’) { res.end() // 预检请求直接返回空响应体 } } })
### postMessage
- window属性
- 跨窗口,跨框架frame、iframe,跨域
- 允许不同源脚本采用异步方式进行有限通信
```js
  otherWindow.postMessage(message, targetOrigin, [transfer])
  // otherWindow:
  iframe.contentWindow // 属性
  window.open // 返回
  window.frames // 访问
  window.onmessage = e => console.log(e.data) // 接收返回数据

Websocket

  • 基于 TCP
  • 全双工通信
  • 应用层协议
  // 客户端
  const socket = new WebSocket('ws://localhost:3000')
  socket.onopen = () => socket.send('message') // 向服务器发送数据
  soket.onmessage = e => console.log(e.data) // 接收服务器返回数据
  // server.js
  const express = require('express')
  const app = express()
  const ws = require('ws')
  const wss = new ws.Server({port: 3000})
  wss.on('connection', ws => {
    ws.on('message', data => console.log(data))
  })

代理服务器转发

  • 代理服务器设置 CORS 请求头字段
    • nginx
      • add_header
    • kangle
      • 回应控制,增加表,标记模块,add_header
    • nodejs
      • response.writeHead
  • 代理服务器向源服务器继续请求
    • nginx
      • 七层 HTTP 代理:配置 http
           http {
          server {
              listen 80;
                  location / {
                      proxy_pass http://127.0.0.1:3000
                  }
              }
          }
        
      • 四层 TCP 代理:配置 stream
         steam {
            upstream proxyServer {
                server 127.0.0.1:3000;
            }
            server {
                listen 80;
                proxy_pass proxyServer;
            }
        }
        
    • kangle
      • 七层 HTTP 代理
        • 请求控制,增加表
        • 目标设置为代理
        • 匹配模块设置原域名和端口,标记模块设置目标域名和端口
    • nodejs
      • 七层 HTTP 代理

const http = require(‘http’) http.request({ host: ‘127.0.0.1’, port: 3000, url: ‘/’ })

document.domain

  • 主域名相同,子域名不同
  • 设置值为 主域名

    iframe

  • window.name
    • 不超过 2MB
    • 同一个iframe
      • 加载跨域页,跨域页设置 window.name
      • 加载同域页,读取 iframe.contentWindow.name
  • location.hash
    • 不会被 URL 编码
    • 加载跨域页,参数跟在 # 后。window.onhashchange 监听 hash 变化
    • 跨域页获取 location.hash,加载同域页,参数跟在 # 后
    • 同域页设置 window.parent.parent.location.hash = location.hash,将参数回传