401 是「你还没证明你是谁」。响应里必须带 WWW-Authenticate,告诉客户端该用哪种方式证明。
上一节的 400 是请求写坏了,这一节是请求没写坏但没带身份。 第八章会展开讲各种认证方案,这里先把 401 这个码本身说清。
一、名字其实取错了
401 叫 Unauthorized(未授权),但它真正的意思是未认证(unauthenticated)——你还没说你是谁。
真正的「未授权」是 403。
这个命名失误在 RFC 里被承认过,但名字改不了了。所以看到 401,永远理解成「去带上凭据再来」。
它必须带 WWW-Authenticate 首部,否则客户端不知道该用 Basic、Bearer 还是别的。
缺了这个首部的 401 是不合规的——客户端只能猜。
二、Basic 认证:两句话说完
客户端把 用户名:密码 用 base64 编一下塞进 Authorization: Basic xxx。服务端解出来比对。
就这两步。
Demo 里 bozai:secret 是 12 字节,base64 之后 16 字节,涨到 1.33 倍。
这个系数是固定的(3 字节变 4 字符)。
关键在于:base64 是编码不是加密。任何人都能一键解回来。
所以 Basic 认证必须跑在 HTTPS 上,否则等于把密码明文广播。这句话每年都还有人踩。
三、今天更常用的是 Bearer
Authorization: Bearer <token>,token 通常是 OAuth 2.0 或 JWT 签发的。
比起 Basic,它有几个好处:不暴露密码、可以带过期时间、可以按权限范围授权。
对应的 WWW-Authenticate 会写成 Bearer realm="...", error="invalid_token",
比 Basic 那一种能表达更多信息。
书里只讲了 Basic 和 Digest(8.2、8.3 节),Bearer 是这本书之后才成为主流的。
2026 年写新系统,默认应该用 Bearer,Basic 只在内部工具和临时调试里出现。
四、动手 Demo:两步走:先被拒,再带凭据
服务端第一次回 401 加 WWW-Authenticate: Basic realm="MySite",客户端构造 base64 凭据再发一次。
if not auth:
return (u'HTTP/1.1 401 Unauthorized',
[(u'WWW-Authenticate', u'Basic realm="MySite"')], b'')
tok = base64.b64encode(u'bozai:secret'.encode()).decode()
s.sendall(_req(extra=[(u'Authorization', u'Basic ' + tok)]))
实跑输出:
--------------------------------------------------------------------
401 Unauthorized:先问你是谁,再给你东西
--------------------------------------------------------------------
第一次(不带凭据) HTTP/1.1 401 Unauthorized
WWW-Authenticate Basic realm="MySite", charset="UTF-8"
第二次(带凭据) HTTP/1.1 200 OK
返回 欢迎回来
原文 bozai:secret(12 字节)
base64 之后 Ym96YWk6c2VjcmV0(16 字节)
膨胀 1.33 倍
关键事实 base64 是**编码不是加密**,任何人都能解回来
Basic 认证只做两件事:把用户名密码拼起来、base64 一下。
所以它**必须跑在 HTTPS 上**,否则等于明文广播密码。
401 与 403 的区别:401 是「你没证明你是谁」,403 是「知道你是谁,但不许看」。
第一次(不带凭据)401、
WWW-Authenticate Basic realm="MySite", charset="UTF-8"——这一行就是「该用哪种方式证明」的说明书。
第二次(带凭据)200 + 返回 欢迎回来。凭据正确,放行。
原文 bozai:secret(12 字节) → base64 之后 Ym96YWk6c2VjcmV0(16 字节),膨胀 1.33 倍。
这一行是本节的硬结论:base64 不提供任何保密性。
顺带一个真实细节:realm 只能是 ASCII。
我第一版写成中文,服务端编 utf-8、客户端按 latin-1 解,
直接乱码——协议里的字符串多半限定 ASCII。
30 秒实验
- 把凭据故意写错,看服务端会不会回 401(会),浏览器会不会重新弹登录框(会, 因为带 WWW-Authenticate)。
- 把 base64 那串直接贴到纸上解码,确认密码明文可见。
- 想想:为什么 Basic 认证不能不带 HTTPS?(因为密码就是明文)
常见误区
- 「base64 是加密」——是编码,一秒就能解。
- 「401 表示没权限」——401 表示没认证,没权限是 403。
- 「401 可以不带 WWW-Authenticate」——不合规,客户端无从下手。
自测三问(点开对答案)
1. 401 与 403 的核心区别? —— 401 是未认证(你是谁还不知道),403 是未授权(知道你是谁但不许)。 2. 401 响应必须带哪个首部? —— `WWW-Authenticate`,说明该用哪种认证方式。 3. 为什么 Basic 认证必须配 HTTPS? —— 因为 base64 可逆,凭据等同于明文传输。401 是「不知道你是谁」。下一节看「知道你是谁,但不给你」。
- ☐ (本节完,下一节 4.4.3 403 Forbidden)