跨域详解及其常见的解决方式

Posted yangrenmu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨域详解及其常见的解决方式相关的知识,希望对你有一定的参考价值。

跨域是什么

跨域是一个域下的网页去请求另一个域下的资源。严格点来说就是两个域的协议、域名、端口任何一个不同时,都会被当作跨域。当跨域访问资源时,会受到浏览器的安全限制,详细的情况可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名 允许
http://www.a.com/a/a.js
http://www.a.com/b/b.js
同一域名,不同文件夹 允许
http://www.a.com:3000/a.js
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应IP 不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允许

为什么限制跨域访问资源

浏览器限制跨域访问资源是一种安全策略,可以预防某些恶意行为。浏览器在每次发起请求时都会带上cookie,试想下,如果没有这总安全策略,evil.com也会拿到用户在secure.comcookieevil.com利用cookie里的信息登录用户的账号,这样用户的数据就被泄露了。跨域限制就是为了避免这种情况的发生。

跨域资源的几种访问方式

  • jsonp

    原理:jsonp之所以能够实现跨域资源的访问,是因为<script>标签不受浏览器同源策略的限制,使用时将src属性指定一个跨域URL,服务器在收到请求后,将数据放到指定的callback里传回来。

    实现:

    前端部分:
    function fetchjsonp(res) {
      console.log(res) // 可以获得服务端的数据,{data: "json data"}
    }
    const script = document.createElement('script')
    script.src = 'http://127.0.0.1:8080?callback=fetchjsonp'
    document.head.appendChild(script)
    服务端:
    const http = require('http');
    const hostname = '127.0.0.1';
    const port = 8080;
    const server = http.createServer((req, res) => {
      if (~req.url.indexOf('?callback')) { // 简单处理 JSONP 跨域的时候
        const obj = {
          "data": 'json data',
        }
        const callback = req.url.split('callback=')[1]
        const jsonData = callback + `(${JSON.stringify(obj)})`
        res.end(jsonData) // 这里最终返回前端的是相当于调用函数 callback({json})
      } else { // 非跨域的时候
        res.statusCode = 200
        res.setHeader('Content-Type', 'text/plain')
        res.end('not jsonp
    ')
      }
    });
    server.listen(port, hostname, () => {
      console.log(`Server running at http://${hostname}:${port}/`);
    });
    优缺点:jsonp优点是兼容性好,支持低版本的浏览器跨域访问。缺点是只支持get请求,不容易判断请求是否失败。
  • CORS

    原理:CORS(cross-origin-resource-sharing)跨域资源共享,其思想是使用自定义的HTTP头部,让浏览器域服务器进行沟通,从而决定请求或响应是成功还是失败。服务器端一般在Access-Control-Allow-Origin中指定对应的域,当浏览器访问对应的资源。
    实现:

    前端部分:
    axios.get('http://127.0.0.1:8080/').then(res => {
      console.log(res) // data from cors
    })
    服务端:
    const http = require('http')
    const hostname = '127.0.0.1'
    const port = 8080
    const server = http.createServer((req, res) => {
      res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:3000') // 设置请求源
      res.setHeader('Access-Control-Allow-Methods', 'get') // 设置请求方法
      res.end('data from cors')
    })
    server.listen(port, hostname, () => {
      console.log(`Server running at http://${hostname}:${port}/`)
    })
    优缺点:优点是支持所有的HTTP请求方法,缺点是不支持老的浏览器;
  • 使用代理

    原理:上面我们已经说了,浏览器的跨域限制是发生在浏览器里的,服务器端是没有的,所以可以使用服务器代理请求其他域的资源,然后在返回给客户端。

    实现:比如说浏览器直接访问http://127.0.0.1:8080会被限制,那么我们可以使用node作代理,来获取http://127.0.0.1:8080返回的资源。
    前端部分: axios.get(‘http://127.0.0.1:8000/‘).then(res => { console.log(res) }) node代理: const express = require(‘express‘) const request = require(‘request‘) const app = express() app.use(‘/‘, function (req, res) { res.set(‘Access-Control-Allow-Origin‘, ‘*‘) const url = ‘http://127.0.0.1:8080‘ // 代理的URL req.pipe(request(url)).pipe(res) }) app.listen(process.env.PORT || 8000)
  • 使用WebSocket

    原理:WebSockethtml5的协议,可以让浏览器与服务器之间建立一个全双工、双向通信。当浏览器使用websocket与服务器建立连接后,HTTP协议会变成websocket协议,websocket协议是不受同源策略限制的,所以可以实现跨域请求资源;

    实现:

    前端部分:
    const ws = new WebSocket("ws://127.0.0.1:8080")
    ws.onopen = function (e) {
      console.log('Connection to server opened')
    }
    ws.onmessage = function (event) {
      console.log('Client received a message: ', event.data) // 客户端接受的数据在 event.data 中
    }
    服务端:
    const WebSocketServer = require('ws').Server
    const  ws = new WebSocketServer({ port: 8080 })
    ws.on('connection', (ws) => {
      ws.send('hello websocket') // websocket 发送给客户端的数据
    })








以上是关于跨域详解及其常见的解决方式的主要内容,如果未能解决你的问题,请参考以下文章

前端 | XSS 的攻击方式及其防御

Ajax 跨域问题及其解决方案

浏览器跨域及其解决方案

常见跨域方法原理及其用例

ajax跨域访问及其解决方案

跨域解决方式