登录时 Network 里看到“明文密码”,正常吗?HTTP/HTTPS 到底怎么防抓包
登录时 Network 里看到“明文密码”,正常吗?HTTP/HTTPS 到底怎么防抓包
我前两天在做博客后台/评论登录的时候,习惯性打开浏览器 DevTools 的 Network 看请求,结果一眼看到请求体里带着:
{ "name": "xxx", "password": "yyy" }
第一反应:完了,这不是“明文密码在网上飞”吗?
但冷静下来想想:浏览器能“显示”出来,不等于网络传输就是明文。这俩是两件事。下面我按我这次的真实场景,把它讲透。
1)为什么 DevTools 里能看到“明文”?
因为你看的不是“线上链路上被截获的包”,而是浏览器自己发出去的请求内容。
在我的项目里,登录请求就是这么发的(前端 fetch 里 JSON.stringify 的 body,本来就是明文字符串):
const login = async (name: string, password: string): Promise<LoginResponse> => {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, password }),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.message || "登录失败")
}
const data: LoginResponse = await response.json()
persistSession(data)
return data
}
你在 Network 看到的“明文账号密码”,本质上就是浏览器发请求前的原始数据(或者浏览器收到响应后的解析结果)。浏览器当然有能力展示它,因为它就是参与者。
真正你关心的“会不会被第三方抓包偷走”,要看的是:从浏览器到服务器之间的传输层是否加密。
2)只要不是明文存数据库就安全?不够
“数据库里不明文保存密码”当然是底线(你项目里是 bcrypt hash):
export async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, 10)
}
export async function verifyPassword(
password: string,
hashedPassword: string
): Promise<boolean> {
return bcrypt.compare(password, hashedPassword)
}
但这只解决了“数据落库后泄露”的风险;登录链路还有一大块风险来自传输过程:
- 你连的是
http://还是https://? - 有没有中间人攻击(同 Wi‑Fi、路由器、运营商劫持、公司代理)?
- 服务器证书是否可信、是否被替换?
- 是否存在前端/服务端日志把密码打出来?
所以正确的理解应该是:
- 存储安全:密码只存 hash(现在做了)
- 传输安全:登录必须走 HTTPS/TLS(需要确保部署与访问方式正确)
- 端侧安全:不要把 token/密码暴露在容易被 XSS 读到的地方(JWT)
3)HTTP 协议本身不负责“加密”,HTTPS 才是关键
很多人会说“HTTP 如何保障不被抓包”。严格讲:
- HTTP:应用层协议,默认不加密,抓包能看到完整内容
- HTTPS:HTTP + TLS(以前叫 SSL),加密发生在 TLS 层
也就是:保护你的是 TLS,不是 HTTP。
TLS 做了三件大事
A. 身份认证(防中间人冒充)
浏览器访问 https://你的域名 时,服务端会出示证书;证书链能被浏览器信任,说明“这台服务器确实是它”。
如果有人在你和服务器之间插个中间人,想把你导向假站点,证书通常会校验不过(除非你设备被安装了恶意根证书/公司强代理,这又是另一类问题)。
B. 密钥协商(让双方得到同一把“会话密钥”)
握手阶段会协商出一把临时会话密钥(一般是 ECDHE 这类方式),之后全程都用它对称加密,速度快。
C. 数据加密与完整性校验(抓到也看不懂,改了会暴露)
这一步才是“抓包看不到明文”的核心:即使攻击者拿到网络包,看到的也是密文;还会有校验,篡改会被发现。
4)那为什么我还能“抓包”看到明文?
这取决于你怎么抓。
- 如果你在浏览器里看 Network:你当然能看到,这是浏览器自己的内容
- 如果你在本机用抓包工具(Charles/Fiddler/mitmproxy)能看到明文:多数情况是因为你安装了抓包工具的根证书,让它能中间人解密,这属于“你自己给自己开了后门”
- 如果你在路由器/同网段抓包:只要是 HTTPS,通常只能看到域名、SNI、握手信息、流量大小与时序,看不到 HTTP body
所以你这次看到“明文账号密码”,在 HTTPS 场景下是正常现象,但前提是:你访问的站点确实是 https://,并且证书正常。
5)回到我的项目:账号密码是怎么被处理的?
登录接口这边,Next.js 的 Route Handler 直接拿 request.json() 解析:
export async function POST(request: Request) {
// Rate limit: 5 次登录尝试 / 分钟
const { limited, resetAt } = checkRateLimit(request, { maxRequests: 5, windowMs: 60_000 })
if (limited) return rateLimitResponse(resetAt)
try {
const { name, password } = await request.json()
// ...省略校验...
const user = await prisma.user.findUnique({
where: { name },
})
// ...省略 verifyPassword...
const token = generateToken({
userId: user.id,
name: user.name,
role: user.role,
})
return NextResponse.json({
user: { id: user.id, name: user.name, role: user.role, createdAt: user.createdAt.toISOString() },
token,
})
} catch (error) {
// ...
}
}
这里面有几个点我自己觉得做得还不错:
- 有简单的登录限流(5 次/分钟),能挡掉一部分暴力猜密码
- 返回 user 时不包含 password(至少不会把 hash 再吐回去)
- 密码校验使用 bcrypt compare
但也有一些“下一步可以更稳”的点(这里先点到为止,不展开到架构大改):
- token 目前会被写进
localStorage(前端persistSession),这对 XSS 更敏感
(更稳的做法是用 HttpOnly Cookie 存 session/token,让 JS 读不到) - 接口返回 token 的同时,如果你在服务端 log 了 request body(现在没有,但以后别加),会有泄露风险
6)HTTP/2 最大的升级是什么?会直接影响什么?
你问到 HTTP/2,我用一句话概括它对“你这个博客项目”的最直接影响:
HTTP/2 最大升级是“多路复用(multiplexing)”:同一个 TCP 连接里并行跑多个请求/响应,不用像 HTTP/1.1 那样排队堵车。
HTTP/1.1 的痛点
以前浏览器为了并发,会对同域名开多个 TCP 连接;而且一个连接里请求容易队头阻塞(Head-of-Line blocking,应用层排队)。
HTTP/2 的核心改变
- 二进制分帧:把数据切成 frame,在一条连接里交错传
- 多路复用:请求 A、B、C 可以并行发,并行回,不用等前一个完整结束
- 头部压缩(HPACK):减少重复 header(cookie、ua、accept 等)带来的浪费
- (曾经有)Server Push:现在大多不推荐/逐渐被弃用
对你的项目会有什么“体感影响”?
你这种 Next.js 应用,页面往往会拉很多静态资源(JS chunk、CSS、图片、字体)+ API 请求。HTTP/2 会让这些资源更容易并行,首屏和交互会更顺滑,尤其是弱网环境下更明显。
但注意:HTTP/2 不等于更安全。安全还是靠 TLS;HTTP/2 只是让传输更高效。现实里浏览器上跑 HTTP/2 基本都建立在 HTTPS 之上,所以你会觉得“上了 HTTPS + HTTP/2 体验更好”,但安全来源是 HTTPS。
7)我给自己定的几个“上线前自检清单”(很实用)
结合你这次问题,我给自己做部署时会过一遍:
- 必须是 HTTPS:域名访问强制
https:// - 打开 HSTS(服务器响应头
Strict-Transport-Security),防止降级回 http - 密码只走 POST body:不要拼到 URL query(query 太容易被日志/历史记录/Referer 暴露)
- 服务端不要打印 password:任何
console.log(body)都要警惕 - 登录加限流:你已经有了(✅)
- Cookie/Token 策略:优先 HttpOnly Cookie,其次再考虑 localStorage(这属于“安全债”,可以按节奏还)
结尾:这次看到“明文”其实是好事
因为它提醒我:安全不是“别明文存库”就结束了,传输、端侧、日志、部署每一层都可能掉链子。
你看到 Network 里有明文账号密码本身并不异常;真正要确认的是:你走的是 HTTPS、证书没问题、服务端不记录敏感信息、密码在库里是 hash。
评论
登录后即可发表评论