跨域作为面试题中的老生常谈,作为一个前端去了解是很有必要的。
最近在面试的时候就频繁被问到,之前没有解决经验被问到真的是一头蒙。(呜呜呜呜,,难过难过,,这就是面试不背面试题的下场(T_T))
今天我们就争取一篇文章把跨域讲清楚!!!
什么是跨域
跨域资源共享(英语:Cross-origin resource sharing,缩写:CORS),用于让网页的受限资源能够被其他域名的页面访问的一种机制。
说人话:让一个网页访问不同源的另一个网页的信息。
浏览器是默认阻止网页向另一个不同源的链接发送请求的,这是为了浏览器的安全考虑,如果允许访问的话用户的cookie和token等内容都会被暴露,很不安全。
什么是同源
同源讲的是url中 协议,域名,端口号 相同
url的结构:
-
protocol:协议 http/https
-
host:主机地址IP/域名
-
ip:任意一台电脑主机都有自己的标识,ipv4/ipv6,ipv4现在用完了几乎(不好记忆)
-
域名:ip地址的美化,方便人们记忆,通过域名访问主机地址,需要通过DNS解析后找到真正的IP
-
服务器名:主机上一个域名可能有不同的功能分区,所以有时在域名前面加上服务器名的前缀服务器名(www.music.)+主域(qq.com/XXX)
-
-
port : 端口号。指主机上分享的窗口,可以想象成房子上的窗口,用于不同主机之间上通信。http默认打开80端口,https默认打开443端口
-
path:访问主机内容的路径
-
query:查询参数。写法: ?name=value&&name=value 。以问号?起始,以name=value的形式向后拼接,不同参数之间&&连接
-
fragment:片段--锚点下面a标签点击后网址中出现的片段,以警号开头#aaa
怎么解决跨域
jsonp解决跨域
jsonp利用在script标签没有跨域的特性,来解决跨域。
具体流程:
- 前端写一个和后端规定好的回调函数来接收请求内容(例如onResponse函数)
- 后端响应请求,并把响应内容写到规定的函数字符串内传给前端(例如res.end(
onResponse(${JSON.stringify(posts)})); - 前端执行对应函数,收到结果
缺点:只能执行get请求,因为script只能接收get请求
cors后端解决跨域
后端解决跨域的思路是:让后端在响应的时候加上对应的响应头,信任相应域名,即可解决跨域。请求分为简单请求和复杂请求,需要配置不同的请求头
- 对于简单请求,乙站点在响应头里添加 Access-Control-Allow-Origin: http://甲站点 即可
- 对于复杂请求,如 PATCH,乙站点需要:
- 响应 OPTIONS 请求,在响应中添加如下的响应头
Access-Control-Allow-Origin: https://甲站点 Access-Control-Allow-Methods: POST, GET, OPTIONS, PATCH Access-Control-Allow-Headers: Content-Type- 响应 POST 请求,在响应中添加 Access-Control-Allow-Origin 头。
- 如果需要附带身份信息,JS 中需要在 AJAX 里设置 xhr.withCredentials = true 。
代理解决跨域
代理分为正向代理和反向代理,正向代理由客户端配置,反向代理由服务端配置。 对于我们这种情况一般使用正向代理。
代理的分类
正向代理
正向代理是位于客户端和目标服务端之间的服务器。客户端向正向代理服务器发送消息,正向代理把我们的消息发送给目标服务器。
用途:正向代理通常用于隐藏客户端的真实身份,绕过防火墙,如VPM。
graph LR
客户端 --> 正向代理服务器 --> 目标服务器
反向代理
反向代理是位于服务器和客户端之间的服务器。客户端向反向代理发送请求,反向代理将请求路由发送到一个或者多个目标服务器上。客户端不知道响应来自哪台服务器。
用途:
负载均衡,安全性和简化客户端请求
graph LR
客户端 --> 正向代理服务器 --> 目标服务器1 & 目标服务器2 & 目标服务器3
vite配置正向代理
vite在本地起一个服务配置正向代理,帮助我们解决跨域。
比如说localhost:3000端口要获取localhost:80的内容
graph LR
3000端口发送请求--> vite代理接收转发 --> 80端口接收
配置例子,配置在vue.config.js内
export default defineConfig({
plugins: [react()],
server: {
port: 3000, //自定义启动时的端口
proxy: {
"/api/1": {
target: "http://localhost:80",
//你的需要请求的服务器地址
changeOrigin: true, // 允许跨域
rewrite: (path) => path.replace(/^\/api^\/1/, ''), // 重写路径把路径变成空字符,
},
},
}
})
这大概就是配置跨域的思路啦~希望每个小伙伴看完都能会配跨域!把跨域讲清楚!
我是发面糕!我们下节再见!(❁´◡`❁)