- Koa开发:入门、进阶与实战
- 刘江虹
- 1005字
- 2022-03-08 10:50:26
2.8 跨域问题
跨域问题是前端开发中经常会碰到的问题,在很多前端面试中经常会问,跨域是什么?它解决了什么样的痛点?那么在讲述Koa实现跨域之前,简单介绍一下跨域的相关知识。
跨域问题通俗来讲,就是浏览器不能执行其他网站的脚本,这是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。所谓同源是指域名、协议、端口均相同。如果有一项不同,就不是同源,看下面几个例子。
- http://www.123.com/index.html
http://www.123.com/server.PHP
只有路径不同,非跨域。 - http://www.123.com/index.html
http://www.456.com/server.php
主域名不同:123/456,跨域。 - http://abc.123.com/index.html
http://def.123.com/server.php
子域名不同:abc/def,跨域。 - http://www.123.com:8080/index.html
http://www.123.com:8081/server.php
端口不同:8080/8081,跨域。 - http://www.123.com/index.html
https://www.123.com/server.php
协议不同:http/https,跨域。
提示
localhost和127.0.0.1虽然都指向本机,但也属于跨域。
先来演示一下跨域会出现什么样的问题。现在有这样一个场景,一个Web服务是http://127.0.0.1:3000,要调用http://127.0.0.1:4000的接口,依据同源策略,这就是跨域调用。首先实现运行在服务端口号为3000的前端页面,代码如下。
<!——- static/index.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>跨域调用接口</title> </head> <body> <button onclick='getUserInfo()'>获取用户信息</button> <span id='data'></span> </body> <script> const getUserInfo = () => { //采用fetch发起请求 const req = fetch('http://127.0.0.1:4000/api/getUserInfo', { method: 'get', headers: { 'Content-Type': 'application/x-www-form- urlencoded' } }) req.then(stream => stream.text() ).then(res => { document.getElementById('data').innerText = res; }) } </script> </html>
功能就是点击“获取用户信息”按钮,调用端口号为4000的服务接口。下面看一下端口号为4000的服务端代码。
const Koa = require('koa') const cors = require('@koa/cors'); const app = new Koa() const Router = require('koa-router') const router = new Router() router.get('/api/getUserInfo', async ( ctx ) => { ctx.body = 'liujianghong' }) app.use(router.routes()) app.listen(4000, () => { console.log('server is running, port is 4000') })
上述代码实现的功能比较简单,就是调用/api/getUserInfo接口时,返回一个字符串。下面看一下端口号为3000的服务端页面,调用端口号为4000的服务接口,结果会不会正常返回,效果如图2-18所示。
图2-18 跨域调用效果图
浏览器报错了,表示这个资源获取是跨域的。这就是浏览器出于安全考虑,做出的同源策略。在平时的开发场景中,有时候是需要跨越调用接口的,应该如何做呢?
Koa解决同源策略的实质是校验请求头,这里有一个协商的过程,第一次请求过来,会问一下服务端:“你好!我是跨域请求你这边的资源,你同不同意?”只有服务端同意后,才可以跨域请求。Koa官方提供了一个中间件@koa/cors用于解决这个问题,代码如下。
const Koa = require('koa') const cors = require('@koa/cors'); const app = new Koa() const Router = require('koa-router') const router = new Router() router.get('/api/getUserInfo', async ( ctx ) => { ctx.body = 'liujianghong' }) // 加载cors中间件 app.use(cors({ origin: '*' })); app.use(router.routes()) app.listen(4000, () => { console.log('server is running, port is 4000') })
这里只增加了@koa/cors中间件,并且通过App装载就可以了。origin设置为“*”,代表任何URL都可以进行跨域请求。再次运行程序,发现跨域的请求可以正常访问后端数据了,效果如图2-19所示。
图2-19 设置cors后的跨域请求
这次可以看到请求正常返回,控制台没有报错。@koa/cors中间件还可以设置很多参数,比如允许哪些方法进行跨域请求,具体用法参考官方文档https://github.com/koajs/cors。
注意
装载@koa/cors中间件一定要在koa-router之前,如果在请求过程中还没有进行cors设置,跨域问题会依然存在。