一、为什么会出现跨域
因为浏览器存在着一个安全功能-同源策略原因导致的。当协议、域名、端口号三者有一个不相同时,就会出现跨域。
二、IP地址、域名、端口号的关系
常见的IP地址分为IPv4与IPv6两大类。目前我们使用的都是IPv4的地址,IPv4地址由32位二进制数组成,常以XXX.XXX.XXX.XXX形式表现。(以上参考于维基百科) IP地址其实就代表着唯一的一台主机。
通常客户端会输入域名(原因之一是IP地址太难记了),通过DNS将域名解析成服务器IP地址,从而访问网站。
端口号是对应一台主机上的多个服务。一台主机对应一个IP,但一个主机上可提供多个服务,每个服务都有一个端口号。
参考链接:网站的域名和端口
三、解决跨域
重点来了!!!
下面我们介绍一下如何解决跨域吧,这里主要介绍三种方式:
1、跨域资源共享(CORS)
只服务端设置Access-Control-Allow-Origin即可,前端无需设置,若要带cookie请求,则前后端都需要设置。
// 设置响应头的中间件
module.exports = async (ctx, next) => {
const contentType = 'application/json; charset=utf-8'
ctx.set('Content-Type', contentType)
// 跨域,添加底下这个即可实现跨域
ctx.set("Access-Control-Allow-Origin", "*")
ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE")
await next()
}
2、JSONP
创建一个js文件:
var express = require('express');
// 90端口的服务,将当前目录作为http服务
var app = express()
app.use(express.static(__dirname))
app.listen(90)
// 91端口的服务,返回数据
var app2 = express()
// jsonp有一个缺点是只能用于get方式
app2.get('/', function(req, res){
var funcname = req.query.callback;
res.send(funcname+"('你好')")
// f('你好')
})
app2.listen(91)
在html文件中:
<!DOCTYPE html>
<html>
<body>
<h1>hello</h1>
<script>
function f(data) {
alert(data)
}
</script>
// script中href、src等不存在跨域问题,只有通过ajax请求才存在跨域问题,jsonp就是通过这个原理
<script src="http://localhost:91?callback=f"></script>
</body>
</html>
参考链接:CORS和JSONP跨域
3、node中间件代理跨域(vue框架)
前提是项目使用vue-cli搭建的,修改的配置文件是vue.config.js
- 项目根目录创建vue.config.js文件
- 添加devServer配置项,配置里边的proxy
module.exports = {
devServer: {
proxy: {
'/api': { // /api表示拦截以/api开头的请求路径
target: 'https://www.vue-js.com/api', // 跨域的域名(一般不需要写路径),这里以vue网址举例,一般只需要写https://www.vue-js.com
// ws: true, // 是否代理websocked
changeOrigin: true, // 是否开启跨域
pathRewrite: { // 重写路径
'^/api': '' // 把/api变成空字符
}
}
}
}
}
在vue页面中:
<button @click"handleClick">跨域请求</button>
...
methods: {
handlerClick() {
// 跨域开启后,会拦截以/api开头的请求路径,并将域名替换成https://www.vue-js.com/api/api/v1/topics,通过pathRewrite属性将/api换成空字符串,最终请求的路径就变成https://www.vue-js.com/api/v1/topics
axios.get('/api/v1/topics').then(res => {
console.log(res)
})
}
}
参考链接:使用vue.config.js解决跨域
自己对跨域一直含糊不清,所以总结出来,嘿嘿~
有不对的地方欢迎指正,欢迎留言~