登录时 Network 里看到“明文密码”,正常吗?HTTP/HTTPS 到底怎么防抓包

zijieLeo
25 分钟
20 次浏览
登录时 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

评论

登录后即可发表评论

暂无评论,快来发表第一条评论吧!