[TOC]
>[success] # 关于跨域
**前提** :**cookie** 是 **跨域不共享** 的,只有 **前端** 跟 **server 端 同一个域** 下,才不会产生跨域。
**问题** :例如 **前端** 启动的服务是 **localhost:8080** , **服务端** 启动一个服务,端口就不能是 **8080端口** ,因为同一台电脑会产生端口占用问题,所以它俩的 **端口不同,就产生了跨域**
**解决** :通过 **nignx** 做代理,让前后端在同一个域下,就不会产生跨域了
**nginx** : **nginx** 可以做哪些事情?
1. 静态服务(静态图片等等)
2. 负载均衡(课里没有讲到)
3. 反向代理
**跨域有几种解决方案** :
1. jsonp
2. 配置cors
3. 前端使用脚手架配置代理
4. 配置nginx反向代理
>[success] ## 前端配置代理
拿 **vue** 举例,前端在 **开发阶段** 出现跨域问题时,通常使用代理的方式来解决跨域,步骤如下:
1. 在 **vue.config.js** 中配置要代理的地址,浏览器报错时未知请求都会匹配到这个地址上
2. 在 **axios** 中的 **baseURL** 中判断一下, **dev** 环境下使用空字符串 "" ,**prod** 环境下使用正式环境地址,也就是说我们 **在开发阶段时调用接口时,接口地址上没有域名,只有后面接口的名称** ,例如:**/api/base/login** ,到浏览器请求时,它才会自动匹配到 **代理地址 + /api/base/login**
>[success] ## nginx配置反向代理
**1. 问题** :假如前端访问的页面地址是:**http://localhost:8001/index.html** 然后该页面调用的接口地址为 **http://localhost:8000/api/blog/list** ,它俩的 **端口不相同** 会产生 **跨域** 。
**2. 如何解决?**
1. 首先下载安装 **nginx**
2. 安装后配置 **nginx.conf** 文件,这里只需要改 **cpu核数** 、**端口号** 以及配置 2 个 **location** , **第1个配置是匹配静态页面 html ,第2个是匹配后端的接口地址**
~~~ nginx
# 1核cpu
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8080; # nginx端口号
server_name localhost; # 当前域名
# 匹配到/都指向下面这个配置静态页面路径
location / {
proxy_pass http://localhost:8001;
}
# 匹配到有/api/都指向到这下方这个nodejs服务下
location /api/ {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
~~~
修改完成后可以使用 `nginx -t` 指令来检查是否有语法错误,如果没有语法错误,执行 `nginx` 指令 **运行 nginx 服务**
3. 这里我们在浏览访问 nginx 的服务地址,http://172.18.2.198:8080/index.html ,结构如下:
**nginx服务域名+端口号 + 本地静态文件地址 = http://172.18.2.198:8080/index.html**
为什么能在 **nginx服务** 上展示 **8001端口服务**的 **index.html** 页面呢?因为这个路径匹配到了 **nginx.conf** 的配置文件中的规则,如果通过nginx 服务地址(http://172.18.2.198:8080)打开的路径,都会被 **nginx.conf** 中的规则解析到,这个地址后面是 **/index.html** , 它被 **location** 中第一个规则 **/** 匹配到了,所以它被代理到了**http://localhost:8001/index.html** 这个地址,并且正常展示了 **index.html** 页面,流程图如下:
![](https://img.kancloud.cn/b2/12/b2124d16fd7cfb8d8c294e446167c0cf_742x401.png)
4. 我们在 **html 页面中调用接口时** ,也需要像 **vue项目** 中配置代理后调用接口一样,**baseURL** 需要为空,**接口的前缀也不允许有接口的域名地址**,代码如下:
~~~
var baseURL = "" // dev环境:空字符串,prod环境:线上地址
var apiPath = "/api/blog/list"
var apiURL = `${baseURL}${apiPath}` // "/api/blog/list"
// html页面中请求接口示例
$.get(apiURL).then(res => {
console.log(res)
})
~~~
这样我们在请求接口时候,他会自动匹配成 **nginx的域名全路径**:**http://172.18.2.198:8080/api/blog/list** ,就跟我们在 **vue** 中做的代理一样,baseURL为空时,他会自动去 **匹配代理**,此时它就会走到 **nginx.conf** 的配置文件中的 **location** 中第 **2** 个规则 **/api/** ,然后它就会被代理到 **http://localhost:8000/api/blog/list** 这个地址下,这样就完美的解决了跨域。
>[success] ## 总结
所谓的 **nginx反向代理** ,实际上就是把 **多个不同的访问地址(路径)** ,在 **nginx** 的服务的 **域名端口** 上进行访问,**这样它们就都使用同一个域名端口号** 了,也就不会产生跨域问题了,然后 **nginx** 在自己的内部自己来根据配置的规则,来区分这些调用的地址应该代理到哪里,就好像一个中间层一样,用户访问浏览器时候访问的实际上是 nginx 的中间层,nginx来做处理来告诉浏览器你应该匹配到哪些地址。
更官方一些的说法就是:
**Nginx反向代理** 可以 **将多个不同的访问地址映射到同一个域名端口上** ,从而 **避免了跨域问题** 。同时, **Nginx作为中间层** , **可以根据用户请求中的某些信息(例如URL路径、Host头等)** 来 **判断应该将请求转发到哪个后端服务器** ,实现请求的动态路由。这样可以提高系统的灵活性和可扩展性,同时也能够有效地保护应用服务器的安全