前端程序员必须要知道的跨域问题以及解决方法(1)

906

前言

最近在做期末课程设计,当前端通过axios向后端发请求时,发现报错了:

1.png 查阅了一番资料,发现这是跨域问题,这篇文章我们就来聊聊跨域问题以及解决方法。

跨域

是什么?

跨域(Cross-Origin)指的是在浏览器中,当一个网页的源(Origin)与正在请求的资源的源不相同时,就会发生跨域请求。

跨域通常发生在:后端响应回来的数据,在浏览器上被终止。即前端的请求后端可以接收到,只不过响应回去时被浏览器终止了。

为什么会出现跨域问题?

因为浏览器实施了同源策略(Same-Origin Policy),该策略限制了不同源之间的交互。 同源策略的目的是保护用户隐私和安全,防止恶意网站获取其他源上的敏感信息或执行未经授权的操作。

那什么是不同源呢?

URL地址由三部分组成:协议号-域名-端口号(有一个不相同就是不同源)

举个例子:协议号为https,域名为localhost,端口号为3000的URL地址与协议号为https,域名为localhost,端口号为8080的URL地址因为端口号不同,所以他们是不同源的,就会出现跨域问题。

浏览器的同源策略虽然保障了安全,但是给我们程序员的开发带来了不便,有问题就有解决方法,接下来我们一起来看一下吧。

解决跨域的方法

JSONP

我们知道通过img标签获取图片地址可以很容易的拿到图片资源,通过<script>标签请求一些Js也能获取到;像img<script>标签从不同域名下加载静态资源,是被浏览器允许的。

原理

基于<script>标签没有跨域限制,我们就可以动态创建script,通过<script>标签src属性向后端传一个函数名(callback),前端再在window上挂上这个函数;后端就在callback函数中传参数,浏览器会把后端响应给前端的东西当做函数来执行。

细分以下几步

  1. 前端创建一个script标签,借助该标签的src属性朝后端发送请求,且前端在window上声明一个函数(callback),并将该函数名拼接在src属性的路径后面作为参数传递给后端。
 <button id="btn">获取数据</button>
    <script>
        function jsonp(url, cb) {
            return new Promise((resolve, reject) => {
                const script = document.createElement('script')
                script.src = `${url}?cb=${cb}`
                document.body.appendChild(script)
                //拿到了后端返回的一个函数
                window[cb] = (data) => {
                    // console.log(data);
                    resolve(data)
                }
            })
        }
        let btn = document.getElementById('btn')
        btn.addEventListener('click', () => {
            jsonp('http://localhost:3000', 'callback').then(res => {
                console.log(res);
            })
        })

    </script>

此时页面上有一个按钮获取数据,点击后就能向后端发请求。

  1. 后端接收到前端的请求且获取到前端传递过来的函数名,将需要响应给前端的数据拼接在该函数的调用中(相当于作为实参传递)。
const koa = require('koa')
const app = new koa()
//传给前端的数据
const data = {
    name: 'song',
    age: '18'
}

const main = (ctx) => {
    const { cb } = ctx.query
    const str = `${cb}(${JSON.stringify(data)})` //向前端传参数
    ctx.body = str

}
app.use(main)
app.listen(3000, () => {
    console.log('项目已启动');
})
  1. 前端接收到后端的响应,相当于在执行window上声明的函数(callback),该函数的参数就是后端响应回来的数据。

此时页面上就能拿到后端传过来的数据:

2.png

缺点

  1. 这种方法利用script标签巧妙地拿到了后端的返回数据,但是需要前后端相互配合,要不然完成不了。
  2. 只能发get请求,浏览器加载Script的scr属性默认是get请求,无法修改。

CROS

CROS全称是"跨域资源共享"(Cross-origin resource sharing),CORS需要浏览器和服务器同时支持。

原理

通过设置响应头,告诉浏览器不需要走同源策略的保护机制。

原生Js写法:

const server = https.createServer((req, res) => {
    res.writeHead(200, {
        "Access-Control-Allow-Origin": '*'//被允许的源
    })
    res.end('hello cors')
})

server.listen(3000)

使用

我们想要使用它的话可以直接npm i @koa/cors,然后const cors = require('@koa/cors')引入到项目中,再直接use就可以了:

app.use(cors({
    origin: '可以发请求过来的源'
}))

CORS已经成为主流的跨域解决方案,我项目中也是这样解决的。

小结

本篇文章简单介绍了跨域是什么以及两种解决跨域的方法,当然肯定不止两种解决方法,我们有机会下次聊。关注作者不迷路(╹▽╹)。现在好累好困,早点睡了~