Http
快来分享你的内容吧~
- 02-14 00:28·Java后端
- 01-15 11:41·后端
- 2024-09-10·@编程小助手 微信: leikooo_
2023-03-17HTTP 缓存有哪些实现方式?什么是协商缓存和强制缓存?查看全文编程导航:HTTP 缓存可以通过以下几种方式进行实现: 浏览器缓存:浏览器可以将最近请求过的资源保存到本地,下次请求时可以直接从本地读取,从而提高访问速度。 代理缓存:代理服务器可以缓存响应,减少对原始服务器的请求次数,从而加快响应速度。 网关缓存:网关可以缓存来自多个原始服务器的响应,然后将响应发送到客户端,从而提高性能。 HTTP 缓存可以分为协商缓存和强制缓存两种类型。 强制缓存是指浏览器在请求资源时
0130分享
2023-03-11HTTP 协议中 GET 和 POST 有什么区别?分别适用于什么场景?查看全文编程导航:HTTP 协议中 GET 和 POST 是两种常用的请求方法,它们的区别如下:1. 参数传递方式不同 GET 请求参数是在 URL 中以键值对的形式传递的,例如:http://www.example.com/?key1=value1&key2=value2。 而 POST 请求参数是在请求体中以键值对的形式传递的。2. 参数传递大小不同 GET 请求参数有大小限制,因为 URL 长度有限制,不同的
31077分享- 2022-10-29"get"与"post"都是常见的"HTTP"请求方法,请从以下角度回答他们的区别:1. 语义的区别2. 应用场景的区别3. 请求url、请求头、请求体的区别4. 其他方面(比如安全、长度限制...)的区别查看全文编程导航:https://github.com/BetaSu/fe-hunter/issues/47#issuecomment-1090104352
514分享
HTTPS页面请求HTTP接口失败?一文讲透Mixed Content
> 前端开发中,有一个高频踩坑场景:前端绑定域名后,HTTP 协议下请求后端 IP 接口一切正常,可一旦开启 SSL 切换为 HTTPS,接口就直接请求失败,控制台报出红色错误 —— 这不是代码 Bug,而是浏览器的安全限制,核心原因就是「Mixed Content(混合内容)」。 ## 一、先明确核心概念:Mixed Content(混合内容) 首先厘清两个基础认知,避免混淆: 1. HTTPS 的本质 HTTPS = HTTP + TLS(Transport Layer Security,传输层安全协议),相当于给 HTTP 传输的数据加了一层加密外套,防止数据被窃听、篡改,保障访问安全;而 HTTP 是明文传输,无任何加密保护。我们常说的「开启 SSL」,本质就是启用 HTTPS 加密。 2. Mixed Content(混合内容)的定义 当 HTTPS 加密页面 中,请求了 HTTP 明文资源 时,就属于 Mixed Content(混合内容)。 浏览器的安全逻辑:HTTPS 页面代表用户处于安全的加密环境,若此时请求 HTTP 明文接口,传输的数据会暴露在风险中,可能被抓包、篡改。因此,浏览器会强制拦截此类请求,这是无法通过后端配置绕过的硬规则。 浏览器控制台的标准报错: ```js Mixed Content: The page at 'https://yourdomain.com' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://your-server-ip:port/api'. This request has been blocked; the content must be served over HTTPS. ``` ## 二、重点解答:HTTPS 页面能否请求 HTTP 接口? 结论:对于接口请求(fetch/axios/XHR),现代浏览器 100% 拦截,无生产可用的例外场景。 浏览器将 Mixed Content 分为两类,仅被动内容有极特殊情况: - 被动内容(Passive Mixed Content):如图片、CSS、字体,部分浏览器可能放行,但会标红警告,无实际生产意义; - 主动内容(Active Mixed Content):如接口请求、JS 脚本、XHR/fetch,所有现代浏览器(Chrome/Edge/Firefox 等)一律强制拦截,这也是我们踩坑的核心场景。 补充:手动关闭浏览器混合内容拦截(仅测试用),无法推广给普通用户,生产环境完全不可用。 ## 三、最简单、一劳永逸的解决方案(Nginx 代理) 核心思路:让前端和接口「同域名、同 HTTPS」,彻底规避 Mixed Content 和跨域,无需修改后端代码。 ### 最终实现效果 前端:https://yourdomain.com (HTTPS 加密,原域名); 接口:https://yourdomain.com/api (同域名、同 HTTPS,通过 Nginx 代理到后端)。 ### Nginx 核心配置(复制即用,替换实际信息) ```Nginx server { listen 443 ssl; server_name [yourdomain.com](https://yourdomain.com); # 你的前端域名 # SSL 证书配置(复用前端证书,无需额外申请) ssl_certificate /your-ssl-path/yourdomain.pem; ssl_certificate_key /your-ssl-path/yourdomain.key; # 前端静态资源配置(无需部署前端可删除) location / { root /your-frontend-path; index index.html; } #核心:接口代理,转发 /api 请求到后端 HTTP 服务 location /api { proxy_pass http://your-server-ip:your-server-port; # 后端 IP + 端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # 可选:80 端口自动跳转 HTTPS,优化用户体验 server { listen 80; server_name [yourdomain.com](https://yourdomain.com); return 301 https://hostrequest_uri; } ``` ### 前端代码修改(1 行搞定) 原写法(硬编码 HTTP 协议和 IP 地址,触发 Mixed Content 拦截): ```js fetch('http://your-server-ip:your-server-port/api/xxx') ``` 修改后(使用相对路径,自动继承页面的 HTTPS 协议和域名,规避混合内容): ```js fetch('/api/xxx') ``` ## 四、终极避坑口诀(记牢不踩坑) 1. HTTPS 页面只能请求 HTTPS 接口,否则触发 Mixed Content 拦截; 2. HTTP 页面可请求 HTTP/HTTPS 接口,无 Mixed Content 限制; 3. 跨域可通过后端 CORS 解决,Mixed Content 只能统一 HTTPS 协议; 4. 接口类主动内容,HTTPS 页面请求 HTTP 接口必失败,无例外。 来源于 https://blog.itrf.cn/posts/ceca/
你的 IP 归属地,是咋被挖出来的?
你是小阿巴,正在家里偷偷欣赏一部很精彩的内容。 你:嗯,真不错啊~  一时兴起,你留下了一条评论:作者牛掰! 结果刚发出去,你就发现评论下面竟然显示:`北京` 你大惊失色:啊,俺被定位了!这网站在监控俺!俺要举报它!  这时,程序员鱼皮突然出现在你身后,擦着鼻血说:淡定,很多平台都会显示用户 IP 归属地的,这很正常。 你吓了一跳:额,你谁啊? 鱼皮:我是古希腊掌管编程的神……精,下面我来科普一下 —— 你的 IP 归属地,是怎么被获取到的?  ⭐️ 本文对应视频版:[https://bilibili.com/video/BV1xCi9BJEx1](https://www.bilibili.com/video/BV1xCi9BJEx1/) ## 怎么获取你的 IP 归属地? 鱼皮:你上网的时候,你的电脑要跟服务器通信来获取网页和数据。 就像寄快递一样,快递员要把包裹送到你家,得知道你家的地址。这个地址就是 **IP 地址**,可以理解为你的网络门牌号。  你:但平台是怎么通过 IP 地址知道俺在 “北京” 的呢? 鱼皮:这就涉及到互联网的组织形式了。 为了方便管理和路由,全球互联网被划分为许多个巨大的网络领地,我们把每个领地叫做 **自治系统**(Autonomous System),简称 AS。  这些 AS 一般由电信、联通这样的运营商(ISP),或者大型互联网公司运营。  每个 AS 负责管理一大批 IP 地址,并规划数据包的传输路线。 运营商在拿到这些 IP 后,会根据自己的机房部署,把不同的 IP 地址段划分给不同城市的网络设备。  为了方便管理,每个 AS 都有一个全球唯一的编号,叫 **ASN**(Autonomous System Number)自治系统编号。  比如 AS4808 是中国联通北京省网络,联通会把其中一段 IP(比如 123.xx.xx.0 到 123.xx.xx.255)分配给他们在北京的接入机房。  你:所以想查俺 IP 的位置,关键就是找到 ASN? 鱼皮:有更简单的方法。全球有很多专业的机构(如 MaxMind、IP2Location)专门收集并汇总了这些 AS 内部 **IP 段和城市的映射关系**,做成了 **IP 地理位置数据库**。  数据库里会记录:这个 IP 段属于 AS4808(中国联通),且目前分配给了北京市的某个接入节点。就知道你大概所属的位置了。  我们打开 [这个网站](https://ip.sb) 查一下,就能看到你家 IP 的完整信息: - Address:123.xx.xx.xx(你的 IP 地址) - ISP:China Unicom(网络服务提供商,中国联通) - ASN:AS4808(自治系统编号) - ASN Organization:China Unicom(ASN 所属的运营商) - Location:北京 中国(地理位置)  你激动了:哇,一目了然啊! ## 能定位多精确? 你紧张起来:等等,那平台管理员岂不是能顺着网线找到俺家门牌号?俺这就把网线拔了!  鱼皮:别慌,通过 IP 地址定位的精确度,取决于数据来源。 像刚才我们用的查询工具,还有微博、抖音这些社交平台,它们都是基于 ASN 和运营商数据来定位的,通常只能定位到市级或者区级,比如广东深圳、上海浦东这种。  你:反正不会显示到 “某栋某室” 对吧?那俺在新闻里看到有人说 “顺着网线抓人” 是怎么回事? 鱼皮:想要找到你的 **精确定位**,可以查询运营商那边详细的分配记录,记录着哪个 IP 在什么时间分配给了哪个用户,甚至有具体的安装地址。  但是,这些数据有严格的隐私保护,只有执法部门依法调查的时候才能查询。普通人和普通平台是查不到的,所以别担心。不做亏心事,不怕鬼敲门。  你若有所思:看来在网络上也不能乱说话呀…… 鱼皮:不过,还有其他精确定位的方法。比如你给 APP 开了 **GPS 权限**,APP 就能直接读取你手机里的 **经纬度坐标**,精度可以达到 10 米以内。  哪怕你关了 GPS,只要你开了 **WiFi 或蓝牙扫描权限**,APP 照样能定位。它们会扫描你附近几个 WiFi 的特征 ID(BSSID),然后去云端数据库一比对,发现你周围这几个 WiFi 都在某栋写字楼里,就能反推出你也在那里。  你心有余悸:还好我的手机权限没有乱开…… 但是鱼皮,平台为什么要显示 IP 归属地呢?会不会侵犯用户的隐私啊? ## 会不会侵犯隐私? 鱼皮:其实这个功能是有依据的。2022 年 6 月,国家网信办发布了《互联网用户账号信息管理规定》,要求平台展示 **合理范围内** 的 IP 归属地信息,目的是便于公众监督,减少网络上的不实信息传播。  而且你看,正规平台只显示大致地区,并不涉及你的具体个人身份信息,也不会暴露你是谁、住在哪里。 你:原来如此!但如果俺是个大明星,粉丝不就知道俺大概在哪里了?万一人多力量大,不小心把俺逮到了怎么办?  对了,俺能不能修改自己的 IP 归属地呢? ## 怎么修改 IP 归属地? 鱼皮坏笑:这太简单了,你只需要买一张高铁票,从北京到天津,半个小时就搞定了~ 你一拍脑袋:妙啊!  鱼皮:哼哼,不过还有更简单的方式 —— 通过代理服务器。 代理服务器就像网络中转站。 正常情况下,你的请求是直接发给目标网站的。 但如果用了代理服务器,你的请求会先发到代理服务器,再由它转发给目标网站。 这样一来,目标网站看到的就是代理服务器的 IP,而不是你的真实 IP。  你恍然大悟:俺懂了,就像俺让朋友帮忙寄快递,寄件地址显示的是朋友家,而不是俺家。  鱼皮:来,我给你演示一下。比如我在北京有台服务器,可以用一个叫 Nginx 的高性能 Web 服务器软件来配置代理。 首先,我在服务器上安装 Nginx(这里利用了宝塔 Linux 面板极速安装):  然后编辑配置文件 `nginx.conf`,配置一个简单的正向代理,也就是让你的请求通过代理服务器转发出去。 ```nginx # 简易正向代理(注意:仅支持 HTTP 流量,不支持 HTTPS) server { listen 8080; location / { # 必须配置 DNS 解析器 resolver 8.8.8.8; # 设置代理目标 proxy_pass http://$http_host$request_uri; # 隐藏真实 IP,防止泄露给目标网站 proxy_set_header X-Real-IP ""; proxy_set_header X-Forwarded-For ""; proxy_set_header Via ""; } } ```  配置好之后,重启 Nginx(或者重载配置):  接下来,当你通过这台服务器的 8080 端口访问 HTTP 网站时,网站看到的就是这台北京服务器的 IP 了。  不过这个简易配置只能代理 HTTP 网站,如果要代理 HTTPS,需要更复杂的配置或者使用专门的代理软件。不过思路是一样的,都是通过中转服务器来隐藏真实 IP。  你兴奋地手舞足蹈:阿巴阿巴,俺也要这样做! 鱼皮:技术虽然不难,但你要注意合理使用技术。 如果是正常的技术学习、企业应用,完全没问题,很多公司都会用代理服务器来管理网络流量。 但千万不要用来逃避平台规则或者做违规的事情。而且现在很多平台都有检测机制,能识别出你是不是用了代理访问。 你好奇道:它们是怎么检测出来的? 鱼皮:常见的方法有这几种 1. 检查 HTTP 请求头,代理访问时会有一些特殊的请求头信息,比如 X-Forwarded-For 2. 检查 IP 地址库,有些服务会维护已知的代理服务器 IP 黑名单 3. 分析访问行为,比如同一个 IP 短时间内有大量不同用户的请求,就很可能是代理 4. WebRTC 泄露检测。浏览器在实现视频通话时会尝试建立点对点连接,这个过程中可能暴露你的真实 IP 地址,即使你用了代理也没用  你:看来想完全隐藏 IP,还有点儿难啊…… 鱼皮:所以最好还是合规使用网络,不做违规的事情哦。 小阿巴:明白了明白了!俺要在你的内容下评论,看看自己的归属地~  ## 更多 💻 编程学习交流:[编程导航](https://www.codefather.cn/) 📃 简历快速制作:[老鱼简历](https://www.laoyujianli.com) ✏️ 面试刷题神器:[面试鸭](https://www.mianshiya.com) 📖 AI 学习指南:[AI 知识库](https://ai.codefather.cn/)
Nginx 跨域 + 无法设置 Cookie 解决办法 + 使用域名访问
首先 F12 看 login 接口对应的网络请求有没有 ⚠️,如果有那是后端的问题,如果没有那是前端的问题 ## 前端问题 前端没有携带 cookie 导致后端识别不到 1) 前端 axios 是否开启了 withCredentials=true 2) 在 OpenAPI 的那边配置项,设置下 withCrendential <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/gW4aFU1njcXhhvtN.webp" alt="img" width="100%" /> ## 后端问题 确认环境 1)确保后端跨域注解或者配置要删除,鱼皮项目一般是 config/CrosConfig.java > 跨域方式只有一种就可以(一般是后端配置或者 Nginx),咱们这里就使用 Nginx 解决跨域 2)如果使用国内服务器,想要使用域名必须要`备案` 3)YML 配置 ```yml server: servlet: session: cookie: domain: 域名或者IP ``` > http 环境就不要使用 secure 和samesite ### 使用宝塔跨域 #### Easy 跨域配置 在宝塔前端配置文件 **非常重要,一定确保「前端请求地址」和「前端运行地址」地址一致!!!** **这种方式需要确保** **1、后端没有配置跨域, 一般是 config/CrosConfig.java (具体内容下面的图片)** **2、前端请求的地址是,前端运行的 IP 或者前端的域名** **比如下面这几种情况** **1)比如前端 IP 是 123.123.123.123 那么前端请求后端的地址也是 123.123.123.123** **2)比如前端 IP 是 123.123.123.123:90 那么前端请求后端的地址也是 123.123.123.123:90** **3)比如前端域名是 leikooo.com 那么前端请求后端请求的地址也是 leikooo.com** <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/g0R8KeESvB5cNcOZ.webp" alt="image.png" width="100%" /> > 前端请求地址和前端运行地址一致 也就是前端 baseURL 请求 192.168.196.158:8000 具体参考自己运行地址 后端跨域配置 <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/21pbGbVFQ5w1QIn7.webp" alt="image.png" width="100%" /> 需要修改宝塔具体位置 <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/rhdSmndvZtGBZ6Yh.webp" alt="image.png" width="100%" /> <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/oQ38EqG7a4mdjyeR.webp" alt="image.png" width="100%" /> 如果是原生的 Nginx 下面是完整的代码,如果是宝塔的话只需要复制两个 `location` 模块到前端配置文件即可 ,**注意一定不要换顺序!** ``` server { listen 80; server_name 前端 IP 比如 126.4.3.3; root 前端路径; location /api { proxy_pass http://127.0.0.1:后端端口; proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_set_header Connection ""; } # 这个要写在下面! location / { index index.html index.htm; try_files $uri $uri/ /index.html; } } ``` --- BUG 比如,下面这种情况: <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/E6qnVzu2ALVtOTiN.webp" alt="image.png" width="100%" /> 所以会导致跨域失败! > 解决方法:前端的 baseUrl 修改成前端运行地址 #### Hard 跨域配置 1、如果之前使用的是下面这种跨域方式也要删除掉/注释! <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/eDZMvNA4CQtfbmsG.png" alt="image.png" width="590px" /> 2、这种方式是前端请求一个独立于前端和后端的端口,比如 前端 80 后端 8080 ,那么前端请求 90 端口让 90 对端口进项反向代理到后端 3、上面的 easy 方式虽然简单,但是如果后端想要使用独立的子域名的情况下就不适用了 --- <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/NJN3DmEuksQN2umo.webp" alt="image-20240914115007224" width="100%" /> <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/mqafC2zfCRO7NcYm.webp" alt="image-20240914115143570" width="100%" /> ```nginx # 后端相关的反向代理+跨域 server { # 这个监听的端口任意都行,但是要注意前端要请求这个端口 listen 90; server_name 前端 IP 比如 126.4.3.3; location / { # 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求 if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) { return 444; } set $origin $http_origin; # 重点!比如: # $origin !~ '^http?://leikooo\.com$ # $origin !~ '^http?://127.0.0.1$ if ($origin !~ '^http?://服务器IP$') { set $origin 'http://服务器IP'; } if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$origin" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header Access-Control-Max-Age 1728000; add_header Content-Type 'text/plain charset=UTF-8'; add_header Content-Length 0; return 204; } if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') { add_header Access-Control-Allow-Origin "$origin" always; add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always; add_header Access-Control-Allow-Credentials true always; } # 反向代理到后端具体运行的端口 proxy_pass http://localhost:后端实际运行端口; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` 请求流程图 <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/pbK8y7G4dTiM88WC.webp" alt="image.png" width="100%" /> 使用域名 前端请求后端的域名,然后在 Nginx 配置跨域和反向代理,访问到真正的后端 ```nginx # 后端相关的反向代理+跨域 server { # http 默认 80 端口 https 默认 443 端口 listen 80; server_name 修改成自己的子域名; # 比如 backend.leikooo.com location / { # 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求 if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) { return 444; } set $origin $http_origin; # 重点!比如: # $origin !~ '^http?://leikooo\.com$ # 下面配置前端域名,比如 leikooo.cn if ($origin !~ '^http?://前端域名$') { set $origin '前端域名'; } if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$origin" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header Access-Control-Max-Age 1728000; add_header Content-Type 'text/plain charset=UTF-8'; add_header Content-Length 0; return 204; } if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') { add_header Access-Control-Allow-Origin "$origin" always; add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always; add_header Access-Control-Allow-Credentials true always; } # 反向代理到后端具体运行的端口 # 如果后端开启了 https 不要忘记请求协议变成 https proxy_pass http://localhost:后端实际运行端口; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` **注意**: 1)前端请求 `90` (上面 server 模块下 listen 的端口)而不是直接请求后端实际运行端口 <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/nIMHYqIdfUjDuCxz.webp" alt="image.png" width="100%" /> 2) 直接请求后端端口,那么 Nginx 就失去了存在的意义! 3)宝塔 + 服务器放行 `90` 端口,这个要注意!!(具体看自己写的是哪个端口) 4)完成 添加 nginx 配置 + 放行端口 正常就没什么问题了! 5)后端配置文件如果写了 samesite 或者 sercure 属性要删除掉! <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/OxyP89FpOL9rkP9n.webp" alt="image.png" width="100%" /> 6)后端写了跨域配置要 删除/注释 一般是 @CrossOrigin 或者 CrosConfig ### 使用原生 Nginx 跨域 经过实际测试,用 nginx 跨域就可以解决 ```nginx user root; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log logs/access.log; sendfile on; keepalive_timeout 65; #gzip on; # 前端配置不是重点 server { listen 80; server_name 前端 IP 比如 126.4.3.3 ; root /root/app/dist; # 访问默写前端页面 404 就是没加下面这行的原因 try_files $uri $uri/ /index.html; location / { index index.html index.htm; } } # 后端相关的反向代理+跨域 server { # 这个监听的端口任意都行,但是要注意前端要请求这个端口 listen 90; server_name 前端 IP 比如 126.4.3.3; location / { # 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求 if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) { return 444; } set $origin $http_origin; # 重点!比如: # $origin !~ '^http?://leikooo\.com$ # $origin !~ '^http?://127.0.0.1$ if ($origin !~ '^http?://服务器IP$') { set $origin 'http://服务器IP'; } if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$origin" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header Access-Control-Max-Age 1728000; add_header Content-Type 'text/plain charset=UTF-8'; add_header Content-Length 0; return 204; } if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') { add_header Access-Control-Allow-Origin "$origin" always; add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always; add_header Access-Control-Allow-Credentials true always; } # 反向代理到后端具体运行的端口 proxy_pass http://localhost:后端实际运行端口; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } ``` 使用域名 要注意一点,使用了下面的配置,就不需要再更改宝塔前端项目的 Nginx 配置(不需要再添加任何配置,比如 proxy_pass 之类的),当然也不用单独再配置一个前端项目 类似这种 <img src="https://pic.code-nav.cn/post_picture/1608460212774109186/KQuO0VVOVab2dchO.webp" alt="image.png" width="100%" /> ```nginx user root; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log logs/access.log; sendfile on; keepalive_timeout 65; #gzip on; # 前端配置不是重点 server { listen 80; # 修改成前端的域名 server_name leikooo.cn; root /root/app/dist; # 访问默写前端页面 404 就是没加下面这行的原因 try_files $uri $uri/ /index.html; location / { index index.html index.htm; } } # 后端相关的反向代理+跨域 server { # 比如我们配置 backend.leikooo.cn 这个是后端域名 # http 默认 80 端口 https 默认 443 端口 listen 80; server_name 修改成自己的二级域名; # 我设置的一般就是 backend.leikooo.cn location / { # 禁止非 GET|POST|HEAD|OPTIONS|PUT|PATCH|DELET 的请求 if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) { return 444; } set $origin $http_origin; # 重点!比如: # $origin !~ '^http?://leikooo\.com$ # 下面配置前端域名,比如 leikooo、.cn if ($origin !~ '^http?://前端域名$') { set $origin '前端域名'; } if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$origin" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header Access-Control-Max-Age 1728000; add_header Content-Type 'text/plain charset=UTF-8'; add_header Content-Length 0; return 204; } if ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') { add_header Access-Control-Allow-Origin "$origin" always; add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always; add_header Access-Control-Allow-Credentials true always; } # 反向代理到后端具体运行的端口 # 如果后端开启了 https 不要忘记请求协议变成 https proxy_pass http://localhost:后端实际运行端口; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } ``` **注意**: 1)前端请求 `9090` 而不是直接请求后端实际运行端口 2)服务器放行 `9090` 端口,这个要注意!!(具体看自己写的是哪个端口) ### Nginx 解决跨域原理 1. 跨域问题的原因 跨域问题是由浏览器的 **同源策略(Same-Origin Policy)** 引起的。同源策略要求: 协议、域名、端口都必须一致。 如果前端和后端运行在不同的域名、IP 或端口上,例如: 前端地址为 http://126.4.3.3 后端地址为 http://126.4.3.3:8080 浏览器会认为它们是不同源,因此会阻止请求,这是跨域问题的本质。 2. 如何解决跨域问题的配置逻辑 Nginx 配置中,location /api 是关键: ``` location /api { proxy_pass http://127.0.0.1:后端端口; proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_set_header Connection ""; } ``` 这里通过 Nginx 的反向代理机制: 将前端通过 /api 路径发起的请求转发到后端(即 http://127.0.0.1:后端端口 )。 对于前端来说,请求的域名和端口仍然是 http://126.4.3.3 ,从浏览器的角度看,请求是同源的。 ### 使用 HTTPS 实际测试使用域名 + HTTPS 也可以解决,解决无法设置 cookie 的问题 教程:https://www.codefather.cn/post/1831983737277050881 ## BUG 1、前端使用域名,但是前端后端使用 ip ,导致 session 设置不上 解决:前后端统一,要用域名都用域名、IP 都用 IP 2、还是不行? 1)检查端口是否放行!!! 2)前端请求的端口是否是 Nginx listen 的端口,不要直接请求实际端口 !!!
【前端】面试题挑战 Day27 HTTP 缓存有哪些实现方式?什么是协商缓存和强制缓存?
HTTP 缓存有哪些实现方式?什么是协商缓存和强制缓存?
【后端】面试题挑战 Day21 HTTP 协议中 GET 和 POST 有什么区别?分别适用于什么场景?
HTTP 协议中 GET 和 POST 有什么区别?分别适用于什么场景?
接口测试
**HTTP协议特点有哪些?**
接口测试
**http常见状态码有哪些?**
get与post有什么区别?
`get`与`post`都是常见的`HTTP`请求方法,请从以下角度回答他们的区别: 1. 语义的区别 2. 应用场景的区别 3. 请求url、请求头、请求体的区别 4. 其他方面(比如安全、长度限制...)的区别
