下面是 第 22 题:HTTP 与 HTTPS、TCP 与 UDP 的区别
这是前端 + 全栈都必考的经典网络题。
我会用:详细版 + 简明对比 + 图解思维 + 速记卡 来讲解。
✅ 第 22 题:HTTP vs HTTPS、TCP vs UDP 的区别
📘 一、HTTP 与 HTTPS 的区别
1. 协议层面
| 协议 | 名称 | 安全性 |
|---|---|---|
| HTTP | 超文本传输协议 | ❌ 明文传输,不安全 |
| HTTPS | HTTP + SSL/TLS | ✔️ 加密传输,安全 |
HTTPS =
HTTP(应用层) + SSL/TLS(安全层) + TCP(传输层)
2. 安全性区别
HTTP(不安全)
- 明文传输
- 数据容易被窃听
- 容易被中间人攻击(MITM)
HTTPS(安全)
- 加密(防窃听)
- 校验完整性(防篡改)
- 服务器身份验证(防伪造)
3. 端口区别
| 协议 | 默认端口 |
|---|---|
| HTTP | 80 |
| HTTPS | 443 |
4. 性能区别
HTTPS 因为需要加密 / 握手,会略慢,但现代优化(HTTP2 / TLS1.3)已经几乎无感。
5. 握手区别(重点)
HTTP:
无握手 → 直接发请求。
HTTPS:
要进行 TLS 握手:
- 验证服务器证书
- 协商加密算法
- 使用对称加密传输数据
面试官爱问:HTTPS 为什么安全?
因为用非对称加密交换对称密钥,然后用对称加密通信。
📘 二、TCP 与 UDP 的区别
1. 是否连接
| 协议 | 是否面向连接 |
|---|---|
| TCP | ✔️ 面向连接(必须三次握手) |
| UDP | ❌ 无连接 |
2. 可靠性
| 协议 | 是否可靠 | 机制 |
|---|---|---|
| TCP | ✔️ 可靠 | 重传、滑动窗口、流量控制、拥塞控制 |
| UDP | ❌ 不可靠 | 不保证顺序、不保证送达 |
3. 速度
| 协议 | 速度 |
|---|---|
| TCP | 较慢(保证可靠性) |
| UDP | 快(无需握手,无需重传) |
4. 是否有序
| 协议 | 是否有序 |
|---|---|
| TCP | ✔️ 有序 |
| UDP | ❌ 无序 |
5. 使用场景
TCP(稳定传输)
需要"正确数据"的使用场景:
- HTTP / HTTPS
- 文件上传下载
- 邮件发送
- 数据可靠性强的业务
UDP(实时性优先)
不要求100%可靠,但要快:
- 视频会议
- 直播
- 游戏实时同步
- DNS(UDP + 53 端口)
📘 三、HTTP vs HTTPS vs TCP vs UDP(总对比表)
| 比较项 | HTTP | HTTPS | TCP | UDP |
|---|---|---|---|---|
| 安全性 | ❌ | ✔️ | ✔️(传输可靠) | ❌ |
| 使用加密 | ❌ | ✔️ | ❌(可加密但非默认) | ❌ |
| 面向连接 | --- | --- | ✔️ | ❌ |
| 速度 | 快 | 略慢 | 较慢 | 最快 |
| 使用场景 | Web 非敏感 | Web 敏感业务 | 可靠传输 | 实时传输 |
| 默认端口 | 80 | 443 | --- | --- |
📘 四、面试官常问的衍生问题(背住必加分)
① 为什么 HTTPS 需要证书?
为了:
- 验证服务器身份
- 防止中间人伪造
- 公钥由权威 CA 签名
② HTTPS 为什么安全?
一句话:
用非对称加密交换对称密钥,用对称加密传输数据。
③ 为什么 TCP 要三次握手?
防止历史连接造成误触发(防止旧包被误认为是新连接)。
三次握手是为了确保双方都具备收发能力。
④ TCP 为什么四次挥手?
因为关闭连接需要双方独立确认:
- 甲:我不发了
- 乙:收到,但我还要发
- 乙:好了我发完了
- 甲:再见
📘 五、速记卡片(10 秒记忆版)
ini
HTTP:明文,不安全,80
HTTPS:加密安全,443,TLS握手
TCP:面向连接,可靠,有序,慢
UDP:无连接,不可靠,无序,快
HTTPS = HTTP + TLS + TCP
TCP 用于可靠场景(Web / 文件)
UDP 用于实时场景(直播 / 游戏)
补充:
跨域(CORS / JSONP / 代理)------更详细的一把梳理(面试 & 实战都能用)
下面把跨域相关的概念、原理、常见方案、服务器/前端示例、常见坑与排查方法都尽量讲清楚(含代码片段),方便你面试和工程中直接套用。
一、先复习:同源策略(Same-Origin Policy)
- 什么叫同源? 协议(scheme)、主机(host)、端口(port)三者都相同则同源。
例如http://example.com:80与https://example.com不是 同源(协议不同)。 - 同源策略的目的:防止跨站窃取敏感数据(浏览器安全沙箱)。它限制了文档/脚本从一个源去读取另一个源的资源(比如读取响应内容)。
二、现代方案(推荐)------CORS(Cross-Origin Resource Sharing)原理
- 浏览器在跨域请求时遵循 CORS,服务器通过响应头声明允许哪些跨域访问,浏览器根据这些头决定是否允许 JS 访问响应。
关键响应头(服务器设置)
Access-Control-Allow-Origin: 必需,指定允许来源。可以是具体域https://foo.com,也可以*(表示允许任意来源,但与凭证不兼容)。Access-Control-Allow-Methods: 允许的方法(GET, POST, PUT, DELETE, OPTIONS)Access-Control-Allow-Headers: 允许的自定义请求头(例如Content-Type, X-Requested-With)Access-Control-Allow-Credentials:true表示允许带 cookie/认证信息(注意:当此为 true 时,Access-Control-Allow-Origin不能为*,必须为明确域名)Access-Control-Expose-Headers: 指示哪些响应头可以被 JS 访问(默认只有简单头可见)Vary: Origin:建议设置,缓存代理根据不同 Origin 保存不同响应
请求类型
- 简单请求(Simple Request) :浏览器直接发送实际请求(GET/POST 若 Content-Type 是
text/plain,application/x-www-form-urlencoded,multipart/form-data),不会发预检(preflight)。 - 需预检请求(Preflight) :当使用非简单方法或自定义头(例如
Content-Type: application/json或自定义X-Token)时,浏览器先发OPTIONS请求询问服务器是否允许(即"预检"),若允许再发送真实请求。
预检流程
- 浏览器发送
OPTIONS(带Origin、Access-Control-Request-Method、Access-Control-Request-Headers)。 - 服务器返回允许的头/方法/是否允许凭证。
- 浏览器若允许则继续发送实际请求。
浏览器端举例(fetch)
javascript
fetch('https://api.example.com/data', {
method: 'POST',
credentials: 'include', // 想带 cookie/凭证必须加这一项
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ a: 1 })
})
.then(r => r.json())
.then(data => console.log(data))
服务器端简易示例(Node/Express)
javascript
// 最简单(允许所有来源,但不能与 credentials 一起用)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');
next();
});
// 带 credentials(必须指定具体域)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'https://your.site.com');
res.setHeader('Access-Control-Allow-Credentials', 'true');
// 预检请求要快速返回 204 或 200
if (req.method === 'OPTIONS') {
res.status(204).end();
return;
}
next();
});
Nginx 配置示例(允许跨域并支持凭证)
rust
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://your.site.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
return 204;
}
add_header 'Access-Control-Allow-Origin' 'https://your.site.com';
add_header 'Access-Control-Allow-Credentials' 'true';
proxy_pass http://backend;
}
三、老办法 / 兼容方案(历史与限制)
-
JSONP(仅限 GET)
-
原理:
<script src="...">不受同源限制,服务器返回一段 JS(通常调用传入的回调函数),从而绕过同源限制读取数据。 -
限制:只支持
GET,安全性差(执行远端 JS),无法携带请求头。 -
示例(前端):
xml<script> function cb(data) { console.log(data); } </script> <script src="https://api.example.com/data?callback=cb"></script> -
服务器返回:
cb({ a: 1 })
-
-
代理转发(推荐在开发与生产中使用)
- 开发环境 :使用 webpack-dev-server / Vite / create-react-app 的 devServer proxy,把
/api转发到https://api.example.com,浏览器认为是同源请求。 - 生产 :用 Nginx 做 reverse proxy,将前端域名下的
/api转发到后端服务(对外只暴露同源域名)。 - 优点:不改后端、不受浏览器 CORS 限制,性能和安全可控。
webpack devServer 示例
yamldevServer: { proxy: { '/api': { target: 'https://api.example.com', changeOrigin: true, secure: false } } } - 开发环境 :使用 webpack-dev-server / Vite / create-react-app 的 devServer proxy,把
-
window.postMessage(跨窗口/跨iframe 通信)
-
场景:父窗口与嵌入的跨域 iframe 通信。
-
安全使用需检查
event.origin。 -
示例:
javascript// 父页面发送 iframe.contentWindow.postMessage({ type: 'hello' }, 'https://other.com'); // 子页面监听 window.addEventListener('message', (e) => { if (e.origin !== 'https://your.trusted.origin') return; // 处理 e.data });
-
-
document.domain(仅限同一级域名,已较少使用)
- 只能把两端都设置成共同的较高一级域(比如
a.example.com与b.example.com都设置document.domain = 'example.com'),现代安全和 iframe 政策使其使用已减少。
- 只能把两端都设置成共同的较高一级域(比如
-
WebSocket
- WebSocket 握手不是典型的 XHR,建立一条持久连接后可以跨域传输数据(服务器需响应握手),适合双向通信场景。
四、常见问题 / 常见报错与排查
Access-Control-Allow-Origin缺失 → 浏览器控制台直接报跨域错误,服务器根本没有返回允许头。- 使用
credentials: 'include'时,Access-Control-Allow-Origin不能是*;必须是具体域。 - 预检
OPTIONS返回 404/500 → 浏览器拒绝发实际请求。解决:服务器对OPTIONS单独返回允许头并 204。 - 自定义请求头(如
X-Token)未出现在Access-Control-Allow-Headers→ 预检被拒。 - 想让 JS 能读自定义响应头,要在服务器设置
Access-Control-Expose-Headers: X-My-Header。 - 浏览器缓存与 Vary:当不同
Origin应该返回不同内容时,后端应加Vary: Origin,否则 CDN/代理可能返回错误的缓存。 - 使用代理时注意
changeOrigin(是否修改 Host header)。
五、安全注意事项
- 尽量不要用
Access-Control-Allow-Origin: *配合Allow-Credentials: true(浏览器会禁止)。 - 小心 JSONP------它执行远端任意 JS,可能被用作 XSS。
- 对允许跨域的来源列白名单,不要把后端随意开放给任意来源,尤其当带有凭证(cookie、token)时。
- 预检机制存在的目的就是在不安全操作前询问服务器,别绕过它。
六:面试/答题速记卡(10 秒)
bash
同源策略:协议+主机+端口相同
主流跨域:CORS(浏览器与服务器配合)
- 简单请求 vs 预检(OPTIONS)
- 核心头:Access-Control-Allow-Origin/Methods/Headers/Credentials/Expose-Headers
老办法:JSONP(仅 GET),代理(devServer/nginx),postMessage/iframe,WebSocket
关键坑:
- credentials + '*' 不行
- 预检要返回 200/204 并带允许头
- 自定义头需出现在 Allow-Headers