401 与 403,以及证书
目标
以 401 和 403 为线索缩小身份认证问题所在的层级,并能够直接从文件中确认两种证书故障模式。
为什么重要
401 表示身份认证失败——“无法确认你是谁”。403 表示授权失败——“知道你是谁,但不允许你执行这项操作”。这一差异会让调查方向截然相反。遇到 401 时应检查凭据本身;遇到 403 时无需改动凭据,只需查看权限配置。如果笼统地称为“权限错误”,就会在错误的方向上浪费数小时。
即使同为 401,原因也各不相同。没有令牌、未知令牌和过期令牌都会返回 401,但处理方式不同,因此必须同时查看响应正文中的原因字符串。
证书方面要确认两点。有效期通过 notAfter 查看,此时还必须同时输出当前时间——因为客户端时钟错误时,正常证书看起来已过期的情况相当常见。名称不匹配本应查看 SAN 而不是 CN,但本练习的证书只有 CN,因此通过主体名称确认。
四种令牌——(헤더 없음), expired-token-2025, readonly-token, fde-prod-2026
两个证书——/opt/data/tls/expired.pem, /opt/data/tls/wronghost.pem(尝试访问的名称是 api.customer.example)
步骤
- 运行
/opt/app/authapi.py,使127.0.0.1:8003/public返回 200。 - 不带 Authorization 标头调用
/private,并将状态码写入/root/auth/no_token.txt。 - 使用
expired-token-2025调用/private,将响应正文保存到/root/auth/expired_reason.txt。 - 使用
readonly-token调用/private,将状态码写入/root/auth/readonly.txt。 - 使用
fde-prod-2026调用/private,将状态码写入/root/auth/ok.txt。 - 将
expired.pem的到期日期保存到/root/auth/cert_expiry.txt。 - 将
wronghost.pem的主体名称保存到/root/auth/cert_cn.txt。 - 在
/root/auth/report.md中总结 401 与 403 的区别以及两个证书的问题。必须包含这两个状态码、api.other.example和到期年份。
参考
curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer 토큰' http://127.0.0.1:8003/privateopenssl x509 -in 파일 -noout -enddate -subject- 要与当前时间比较,请同时输出
date -u。 - 常见错误 1:在第 3 步中只保存状态码。这里需要的是 401 的原因。
- 常见错误 2:发送令牌时,标头格式中没有
Bearer。这样令牌根本不会被识别。
启动身份认证网关
运行 /opt/app/authapi.py,使 127.0.0.1:8003/public 返回 200。
运行 /opt/app/authapi.py 后,它会在 127.0.0.1:8003 上监听。/public 无需身份认证即可访问。
不带令牌调用
不带 Authorization 标头调用 /private,并将状态码写入 /root/auth/no_token.txt。
不带 Authorization 标头调用 /private,记录返回的状态码。
获取过期原因
使用 expired-token-2025 调用 /private,将响应正文保存到 /root/auth/expired_reason.txt。
过期令牌也会返回 401。仅凭状态码无法知道原因,因此请保存响应正文。
确认权限不足
使用 readonly-token 调用 /private,将状态码写入 /root/auth/readonly.txt。
readonly-token 能通过身份确认。观察此时返回的状态码与 401 有何不同。
确认正常认证
使用 fde-prod-2026 调用 /private,将状态码写入 /root/auth/ok.txt。
使用 fde-prod-2026 令牌即可通过。记录成功状态码。
检查过期证书
将 expired.pem 的到期日期保存到 /root/auth/cert_expiry.txt。
可以使用 openssl x509 查看证书的有效期。保存其到期日期。
检查名称不匹配的证书
将 wronghost.pem 的主体名称保存到 /root/auth/cert_cn.txt。
提取 wronghost.pem 的主体名称。它与尝试访问的名称不同。
编写诊断报告
在 /root/auth/report.md 中总结 401 与 403 的区别以及两个证书的问题。必须包含这两个状态码、api.other.example 和到期年份。
总结 401 和 403 分别表示哪一种失败,以及两个证书各自存在什么问题。