使用方法
- 输入用户名和密码。
- 把生成的 Authorization 请求头复制到你的客户端中,或者用 curl 命令测试请求。
- 如需查看现有请求头,把它粘贴到解码区域,即可显示用户名和密码。
HTTP Basic 认证的工作原理
Basic 认证由 RFC 7617 定义。访问受保护的资源时,服务器返回 401 Unauthorized 和 WWW-Authenticate: Basic realm="..." 响应头。客户端随后用冒号连接用户名和密码,将结果进行 Base64 编码,并在每个请求中发送:
Authorization: Basic base64(username ":" password)
# RFC 7617 中的示例:用户 "Aladdin",密码 "open sesame"
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
浏览器会自动完成这一过程并弹出登录对话框;脚本和 API 客户端则通常在第一个请求中就直接带上该请求头,而不必等待服务器质询。由于冒号用来分隔两个值,用户名中不能包含冒号,密码中则可以。服务器可以在质询中加上 charset="UTF-8",表示非 ASCII 字符的凭据应使用 UTF-8 编码。
Base64 不是加密
请求头看起来像乱码,但任何看到它的人都能在几秒内还原出密码,用本页的解码功能或任何 Base64 解码 工具都可以。因此 Basic 认证只能在 HTTPS 下使用,由 TLS 在传输过程中加密请求头。另外还要注意:
- 凭据会随每个请求发送,只要有一次请求走了明文 HTTP,就会泄露;
- 代理、负载均衡器和调试工具可能会记录
Authorization请求头,除非专门配置不记录; - 浏览器会一直记住输入过的凭据,直到关闭浏览器,而且没有标准的退出登录方式。
对于公开 API,可撤销的 API 令牌或 OAuth 更合适。Basic 认证仍然适用于内部工具、测试环境网站,以及通过 TLS 进行的服务器间调用。
在代码中发送请求头
# curl 会自动生成请求头
curl -u 'user:password' https://api.example.com/
// JavaScript fetch(btoa 只能处理 Latin-1 字符)
fetch(url, { headers: { Authorization: 'Basic ' + btoa('user:password') } })
# Python requests
requests.get(url, auth=('user', 'password'))
不要把凭据直接写在 URL 中,例如 https://user:password@host/。RFC 3986 已弃用这种写法,它会留在浏览器历史和服务器日志里,现代浏览器也对其加以限制。
常见问题
如何解码 Basic 认证请求头?
把请求头粘贴到解码区域,用户名和密码会立即显示出来。任何 Base64 解码工具都能得到同样的结果,这也正是该请求头只能通过 HTTPS 传输的原因。
密码中可以包含冒号吗?
可以。服务器会在解码后的第一个冒号处分割,之后的所有内容都属于密码。但用户名中不能包含冒号。
HTTP Basic 认证安全吗?
在 HTTPS 下配合强密码且不重复使用,传输过程中的凭据是受保护的。但凭据会随每个请求发送,也不能像令牌那样自动过期。切勿在明文 HTTP 下使用。
为什么密码含有中文或带重音的字符时登录失败?
charset="UTF-8";如果没有声明,一些较旧的服务器可能按 ISO-8859-1 处理,比较的就是不同的字节。我的密码会被发送到别处吗?
不会。请求头由浏览器中的 JavaScript 生成,不会传输任何数据。不过,与他人分享生成的 curl 命令时,最好使用测试账号。