Q1: 什么是DNS?
一、DNS 是什么?为什么需要它?
核心定义
DNS = 分布式数据库 + 查询协议 ,用于将人类可读的域名(如
www.example.com)转换为机器可识别的 IP 地址(如93.184.216.34)。
类比理解
ini
🌍 互联网 = 全球电话网络
📇 DNS = 智能电话簿 + 接线员系统
👤 你 = 客户端(浏览器/后端服务)
你想联系 "阿里巴巴客服"(域名)
→ 查电话簿(本地缓存)
→ 问小区物业(本地DNS)
→ 物业问市电信局(根/顶级域名服务器)
→ 最终拿到号码:0571-85022088(IP地址)
→ 拨号建立连接
为什么不用 IP 直接访问?
| 问题 | DNS 的解决方案 |
|---|---|
| ❌ IP 难记忆 | ✅ 域名人类可读 |
| ❌ 服务器迁移需改所有客户端配置 | ✅ 域名不变,只改 DNS 解析记录 |
| ❌ 无法做负载均衡 | ✅ 一个域名可解析到多个 IP(轮询/地域调度) |
| ❌ 单点故障 | ✅ 快速切换 DNS 记录实现故障转移 |
二、DNS 的层次结构(树状分布式设计)
scss
. (根域名,13组根服务器)
|
+---------------+---------------+
| | |
.com .org .cn (顶级域名 TLD)
| | |
+----+----+ +----+----+ +----+----+
| | | | | |
example google wikipedia alibaba baidu (二级域名)
| | | | | |
www api mail www docs www shop (子域名/主机记录)
关键角色
| 角色 | 职责 | 示例 |
|---|---|---|
| 根域名服务器 | 管理顶级域名服务器地址 | a.root-servers.net |
| TLD 服务器 | 管理某顶级域下的所有域名 | .com 服务器知道 example.com 的 NS 记录 |
| 权威域名服务器 | 存储具体域名的解析记录 | ns1.alibaba.com 存储 www.alibaba.com → IP |
| 本地 DNS 服务器 | 为用户递归查询,提供缓存 | 运营商分配的 114.114.114.114 |
✅ 设计精髓:分层 + 缓存 + 分布式,避免单点瓶颈,查询效率极高。
三、DNS 解析完整流程(递归 + 迭代)
假设用户在浏览器访问 y.abc.com :

Q2:什么是CDN?
CDN(Content Delivery Network,内容分发网络) 是构建高性能、高可用服务时不可或缺的"加速器"。
它不仅是前端静态资源的"快递站",更是后端架构中降低源站压力、提升全球访问速度、抵御流量攻击的关键基础设施。
核心定义
CDN = 分布式边缘节点网络 + 智能调度系统,通过将内容缓存到离用户最近的节点,实现"就近访问",降低延迟、减轻源站压力。
类比理解(快递系统)
scss
🌍 传统模式(无CDN):
用户(上海) → 互联网 → 源站服务器(北京) → 返回内容
⏱️ 延迟高 + 源站带宽压力大
🚀 CDN模式:
用户(上海) → 边缘节点(上海机房) → 直接返回缓存内容
⏱️ 延迟低 + 源站零压力(缓存命中时)
📦 缓存未命中时:
边缘节点(上海) → 回源 → 源站(北京) → 缓存到上海节点 → 返回用户
🔄 后续上海用户都从本地节点获取
为什么后端必须了解 CDN?
| 问题 | CDN 的解决方案 | 后端收益 |
|---|---|---|
| ❌ 用户访问慢(跨地域/跨国) | ✅ 边缘节点就近响应 | 提升用户体验,降低跳出率 |
| ❌ 源站带宽被打满(突发流量) | ✅ 90%+ 请求被边缘节点拦截 | 节省带宽成本,避免服务雪崩 |
| ❌ 静态资源占用应用服务器资源 | ✅ 静态/动态分离,CDN 托管静态文件 | 应用服务器专注业务逻辑 |
| ❌ DDoS/CC 攻击直接打到源站 | ✅ CDN 作为"盾牌"吸收攻击流量 | 提升系统安全性 |
Q3:Cookie,Session和Token之间有什么区别?
Cookie、Session 和 Token 是解决 HTTP 无状态(Stateless) 问题的三种核心方案。
核心概念速览
| 机制 | 存储位置 | 本质 | 关键特点 |
|---|---|---|---|
| Cookie | 客户端 (浏览器) | 一段文本数据 | 浏览器自动携带,有大小限制 (4KB),易被篡改 |
| Session | 服务端 (内存/Redis) | 服务器端的会话记录 | 依赖 Cookie 传 SessionID,服务器有状态,单机友好 |
| Token (如 JWT) | 客户端 (浏览器/App) | 自包含的加密字符串 | 服务端无状态,适合分布式/移动端,需防泄露 |
💡 一句话总结:
- Cookie 是"存储机制"(存在哪?存在浏览器)。
- Session 是"会话管理"(数据存在服务器,靠 Cookie 传 ID)。
- Token 是"认证凭证"(数据存在客户端,服务端只验签名)。
详细工作流程对比
1️⃣ Cookie + Session 模式(传统 Web 应用)
这是最经典的方案,适合单体应用。
ini
👤 用户 🌐 浏览器 🏢 服务端 (Session 存储)
| | |
| 1. 输入账号密码 | |
| --------------------->| |
| | 2. POST /login |
| | -----------------------> |
| | | 3. 验证通过
| | | 4. 创建 Session 数据
| | | (userId=1001, role=admin)
| | | 5. 生成 SessionID=xyz123
| | | 6. 存储 Session 到 Redis/内存
| | | Key: xyz123, Value: {...}
| | 7. 响应 Set-Cookie: |
| | JSESSIONID=xyz123 |
| | <----------------------- |
| 8. 浏览器保存 Cookie | |
| | |
| 9. 访问 /profile | |
| --------------------->| |
| | 10. 请求自动携带 Cookie |
| | JSESSIONID=xyz123 |
| | -----------------------> |
| | | 11. 根据 ID 查 Session 数据
| | | 12. 返回用户信息
| | <----------------------- |
| 13. 显示页面 | |
- 优点:安全(敏感数据在服务端),实现简单。
- 缺点 :服务器有状态,集群部署需解决 Session 共享 (如 Redis 集中存储)或 会话保持(Nginx ip_hash)。
2️⃣ Token 模式(如 JWT,现代 API/微服务)
这是前后端分离、移动端、微服务的主流方案。
lua
👤 用户 🌐 客户端 🏢 服务端 (无状态)
| | |
| 1. 输入账号密码 | |
| --------------------->| |
| | 2. POST /login |
| | -----------------------> |
| | | 3. 验证通过
| | | 4. 生成 Token (JWT)
| | | Header.Payload.Signature
| | | (包含 userId, exp, 签名)
| | 5. 响应 { token: "..." } |
| | <----------------------- |
| 6. 客户端保存 Token | | (不存储 Session)
| (LocalStorage/内存) | |
| | |
| 7. 访问 /api/profile | |
| --------------------->| |
| | 8. 请求头携带 |
| | Authorization: Bearer |
| | <token> |
| | -----------------------> |
| | | 9. 解析 Token
| | | 10. 验证签名 + 有效期
| | | 11. 提取 userId 处理业务
| | | (无需查数据库/Redis)
| | 12. 返回数据 |
| | <----------------------- |
| 13. 显示数据 | |
- 优点:服务端无状态,易扩展,支持跨域,适合移动端。
- 缺点 :Token 一旦签发,难以撤销(除非引入黑名单);Payload 不能存敏感信息(因为只是 Base64 编码,可被解码)。
常见面试坑点 & 解决方案
1. Token 被窃取了怎么办?
-
问题:XSS 攻击拿到 Token,可冒充用户。
-
解决:
- HTTPS 强制加密传输。
- Token 存 内存 (JS 变量) 而非 LocalStorage。
- 短有效期 (如 15 分钟) + Refresh Token 轮换。
- 关键操作(支付/改密)要求二次验证。
2. 分布式 Session 怎么实现?
-
问题:用户请求打到服务器 A,Session 在 A;下次请求打到 B,B 没有 Session。
-
解决:
- Session 复制:A 同步给 B(流量大,不推荐)。
- 会话保持 :Nginx 配置
ip_hash,同一 IP 始终打到同一台(扩容/故障不友好)。 - Session 集中存储 (推荐):所有服务器读写 Redis Cluster。
3. 如何做到 Token 的"注销"功能?
-
问题:JWT 无状态,签发后服务端无法主动失效。
-
解决:
- 短效 Token:让它快点过期。
- 黑名单机制:用户注销时,将 Token ID (jti) 加入 Redis 黑名单,设置剩余过期时间为 TTL。网关/中间件验签时查黑名单。
- 版本号 :用户表加
token_version字段,Token 里也带版本号,不一致则失效(需查库,牺牲部分无状态优势)。
4. Cookie 的 SameSite 属性是什么?
-
背景:防止 CSRF 攻击。
-
值:
Strict:完全禁止第三方 Cookie(最安全,但影响体验)。Lax:允许顶级导航请求携带(默认值,平衡安全与体验)。None:允许所有第三方 Cookie(必须配合Secure,用于跨站场景)。
Q4: 讲一下JWT Token?
JWT 是什么?
核心定义
JWT (RFC 7519) 是一种开放标准,用于在双方之间安全地传输信息作为 JSON 对象 。 核心特点:自包含 (Self-contained) 和 无状态 (Stateless) 。
类比理解
scss
🪪 Session 机制 = 小区门禁卡
• 卡上只有一个编号 (SessionID)
• 保安 (服务器) 需要查登记表 (Redis/Database) 才知道你是谁
• 缺点:每个保安室都要有同样的登记表 (集群共享麻烦)
🛂 JWT 机制 = 护照
• 护照上直接印着你的信息 (姓名、国籍、有效期) + 政府公章 (签名)
• 海关 (服务器) 只需验证公章真伪,无需查数据库
• 优点:任何海关都能验,无需联网查表
• 缺点:护照丢了很难作废 (撤销困难)
二、JWT 结构详解(核心!)
JWT 是一个长字符串,由 . 分隔成三部分:Header.Payload.Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1️⃣ Header (头部)
描述 JWT 的元数据,主要是算法 和类型。
json
{
"alg": "HS256", // 签名算法:HMAC SHA256
"typ": "JWT" // 令牌类型
}
⚠️ 注意 :Header 只是 Base64 编码,任何人可解码查看,不要放敏感信息。
2️⃣ Payload (负载)
存放实际数据,称为 Claims (声明) 。
json
{
"sub": "1234567890", // 主题 (通常是用户 ID)
"name": "John Doe", // 用户名称
"role": "admin", // 用户角色
"iat": 1516239022, // 签发时间 (Issued At)
"exp": 1516242622 // 过期时间 (Expiration Time) ⚠️ 关键字段
}
⚠️ 严重警告:
- Payload 只是 Base64 编码 ,不是加密!任何人都能解码看到内容。
- 严禁存放密码、手机号、银行卡号等敏感信息。
- 尽量精简,因为 JWT 会随每次请求发送,过大会浪费带宽。
3️⃣ Signature (签名)
防止篡改的核心。服务器用密钥 (Secret) 对 Header + Payload 进行签名。
scss
// 伪代码
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key // 只有服务器知道
)
✅ 作用 :客户端修改了 Payload(如把
role: user改成role: admin),签名就会失效,服务器验证时会拒绝。
常见面试坑点 & 排查思路
1. JWT 如何做到单点登录 (SSO)?
- 方案:认证中心统一签发 JWT,各个子系统共享公钥(RS256 算法)验签。
- 流程:用户登录认证中心 → 获取 JWT → 访问子系统 A → A 验签通过 → 访问子系统 B → B 验签通过。
2. Token 太大影响性能怎么办?
-
原因:Payload 放了太多数据。
-
解决:
- Payload 只放
userId和role,其他信息查库/缓存。 - 开启 HTTP 压缩 (Gzip/Brotli)。
- 考虑改用 Session(如果带宽是瓶颈)。
- Payload 只放
3. 如何排查「Token 验证失败」问题?
- 检查时间同步 :服务器时间不一致会导致
exp验证失败(NTP 同步)。 - 检查密钥 :签发和验证的
secret是否一致。 - 检查算法:签发用 HS256,验证是否误配为 RS256。
- 检查格式 :Header 是否带了
Bearer前缀,是否有空格。 - 查看日志 :JWT 库通常会抛出具体异常(
TokenExpiredError,JsonWebTokenError)。