小白也能看懂的解决跨域的三种方式

前言:

由于浏览器为了防止恶意网站窃取用户在其他网站的敏感信息,如用户登录状态、个人数据等。于是浏览器就会开启同源策略。 同源策略:它限制一个源的文档或者加载的 JS 脚本,与另外一个源的资源进行交互,帮助我们阻隔恶意文档,减少被攻击的媒介

同源策略

  • 一个 "源" 是由协议(scheme)、主机(host)和端口(port)来定义的。只有当这三个部分完全相同的时候,两个网页才被认为是同源的。
  • 是浏览器的一种安全机制,它规定了只有来自相同 "源" 的脚本才能访问当前网页的文档对象模型(DOM)、本地存储(localStorage 等)、会话存储(sessionStorage)、Cookies 以及其他敏感资源。

解决跨域

跨域的本质就是使得浏览器不触发同源策略

JSONP

使用JSONP方式实质上是借用了浏览器的一种取巧方式实现,它可能看起来不怎么优雅。由于浏览器在对包括imgscriptradio等html标签发送的网络请求并不会触发浏览器使用同源策略的,于是我们便可以利用这个漏洞实现跨域问题。

首先我们创建一个server.js,使用node在3000端口处打开服务器

js 复制代码
const http = require('http')

http.createServer((req, res) => {
  res.end('success')
})
  .listen(3000)

其次创建index.html,将监听的地址放入script的src中

js 复制代码
 function JSON(url) {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script')
        script.src = url
        document.body.appendChild(script)
      })
    }


    JSON('http://localhost:3000')
      .then(res => {
        console.log(res);
      })

我们封装了一个JSONP函数,为了拿到结果的异步操作,使得该函数返回一个Promise对象。但很快我们就会发现一个问题,我们根本没有拿到返回的数据显示的是该数据success没有被定义,并且正常的GET请求是能够传递params参数。

转换一个思路,如果我们通过window全局去触发这个函数呢?在加载全局的时候直接将该方法挂载上去,在服务器响应回来拿到数据的时候,直接将挂载在window上的方法触发,并且通过url传递我们需要的params参数。

js 复制代码
    function JSON(url, callback) {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script')
        window[callback] = function (data) {
          resolve(data)
        }
        script.src = `${url}?callback=${callback}`
        document.body.appendChild(script)
      })
    }


    JSON('http://localhost:3000', 'callback')
      .then(res => {
        console.log(res);
      })

同时后端那边也需要协助我们完成这一次操作,后端需要再拿到url的请求后,处理分离出函数名,并将后端的实参传递到挂载在window的函数上面。

js 复制代码
const http = require('http')

http.createServer((req, res) => {
  const query = new URL(req.url, `http://${req.headers.host}`).searchParams
  if (query.get('callback')) {
    const callback = query.get('callback')
    const data = '我是数据'
    const result = `${callback}("${data}")`
    res.end(result)
  }
  res.end('success')
})
  .listen(3000)

值得一提的是JSONP方式只能过去处理GET请求,这是由于script标签本身只能发送GET请求,从而限制了JSONP方式只能处理该请求

WebSocket

使用WebSocket协议,WebSocket 连接建立时会使用 HTTP 协议进行握手。客户端发起一个特殊的 HTTP 请求,这个请求中包含一些特殊的头部信息,用于表明这是一个 WebSocket 升级请求。

WebSocket 是全双工协议,一旦连接建立,服务器和客户端可以在这个连接上双向自由地发送数据,不需要像 HTTP 那样每次重新建立连接来进行通信。

首先建立后端的服务器

js 复制代码
const WebSocket = require('ws')
const ws = new WebSocket.Server({ port: 3000 })
ws.on('connection', (obj) => {
  obj.on('message', (data) => {
    obj.send('我是 WebSocket')
  })
})

建立连接请求

js 复制代码
function web_Socket(url) {
      return new Promise((resolve) => {
        const socket = new WebSocket(url)
        socket.onopen = () => {
          socket.send('http://localhost:3000')
        }
        socket.onmessage = (res) => {
          resolve(res.data)
        }
      })
    }

    web_Socket('http://localhost:3000').then(data => {
      console.log(data);
    })

CORS

采用 CORS (跨域资源共享),一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),来访问加载服务器上的资源。

其实际上就是通过添加在响应头中的特殊字段,使得浏览器不会使用同源策略对响应资源进行干扰。

后端建立服务器同时设置允许的源,当然我们也能设置成'Access-Control-Allow-Origin': '*' 这样会允许所有的源对服务器进行访问,我们可以设置自己响应的源进行访问。

js 复制代码
const http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:5500'
  })
  res.end('hello world')
}).listen(3000);

前端通过ajax发送请求

js 复制代码
const xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:3000')
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);

      }
    }

总结

总而言之,所有的跨域解决方式都是需要通过后端进行特殊的处理操作,或者是前后端一起对接工作进行特殊的处理。当然解决跨域的方式远不止这些,还有诸如postMessage、nginx等方式能解决跨域问题,大家可以自行进行学习拓展哦!

相关推荐
狗狗显卡10 分钟前
一些计算机零碎知识随写(25年1月)
前端
CHANG_THE_WORLD20 分钟前
Linux 基础七 内存
linux·服务器·前端
鹿屿二向箔25 分钟前
JavaScript (JS) 前端开发
javascript
Z3r4y44 分钟前
【Web】极简&快速入门Vue 3
前端·javascript·vue.js·vue3
cxr8281 小时前
Windows 11 系统中npm-cache优化
前端·windows·npm
小小小小宇1 小时前
如何在 React 中实现 Vue 的插槽功能
前端
工业甲酰苯胺1 小时前
Java Web学生自习管理系统
java·开发语言·前端
百里落云1 小时前
2024年终总结,人生已过半,一半回忆,一般继续!
面试
网络安全-老纪2 小时前
[网络安全]DVWA之XSS(DOM)攻击姿势及解题详析合集
前端·web安全·xss
蓝天星空2 小时前
html生成注册与登录代码
javascript·css·html