Curl摘要认证失败求助:无法发起二次请求完成认证
Curl摘要认证无法发起二次请求的问题解决
我通过Shell脚本使用Curl尝试通过Digest Authorization连接HTTP服务器,但Curl始终没有发起完成摘要认证所需的第二次请求。
Curl输出如下:
* Expire in 1 ms for 1 (transfer 0x4fb960) * Trying 192.168.17.24... * TCP_NODELAY set * Expire in 200 ms for 4 (transfer 0x4fb960) * Connected to xxx (192.168.17.24) port 80 (#0) * Server auth using Digest with user 'user' > POST /config/timeofuse HTTP/1.1 > Host: xxx > User-Agent: curl/7.64.0 > Accept: application/json, text/plain, */* > Content-Type: application/json > Content-Length: 0 > < HTTP/1.1 401 Unauthorized < X-WWW-Authenticate: Digest realm="Webinterface area", charset="UTF-8", algorithm=MD5, nonce="6463d513:3927ccc8e06b0a9d4ec28f0bc9d863bc", qop="auth" < Content-Type: text/html < Content-Length: 347 < Date: Tue, 16 May 2023 19:10:11 GMT < Server: webserver < <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>401 Unauthorized</title> </head> <body> <h1>401 Unauthorized</h1> </body> </html> * Connection #0 to host xxx left intact
我推测问题出在Curl需要标准的WWW-Authenticate响应头,但服务器返回的是X-WWW-Authenticate头,而且因为是嵌入式设备,没法修改服务器配置。想请教两个问题:
a) 我的推测是否正确?还是有其他问题?
b) 有没有办法让Curl把X-WWW-Authenticate头当作WWW-Authenticate头处理?
我试过httpie,遇到同样问题;查阅了Curl手册,未找到相关设置。
问题a的解答
你的推测完全正确。根据HTTP标准,摘要认证要求服务器在401响应中返回WWW-Authenticate头传递认证参数,而Curl、httpie这类工具只会识别标准的WWW-Authenticate头,对非标准的X-WWW-Authenticate头不会触发自动处理流程,因此不会发起第二次携带认证信息的请求。
问题b的解答
Curl本身没有直接配置项支持识别X-WWW-Authenticate头,但可以通过两种方式解决:
方法1:手动构造Digest认证头
- 从服务器返回的
X-WWW-Authenticate头中提取关键参数:realm、nonce、qop、algorithm。 - 手动计算摘要认证所需的哈希值,构造
Authorization头。 - 在Curl请求中直接添加该头。
示例操作:
假设提取到的参数为:
- realm: "Webinterface area"
- nonce: "6463d513:3927ccc8e06b0a9d4ec28f0bc9d863bc"
- qop: "auth"
- algorithm: MD5
用户名user,密码your_password,请求方法POST,路径/config/timeofuse。
计算哈希值:
# 计算HA1:MD5(用户名:域:密码) HA1=$(echo -n "user:Webinterface area:your_password" | openssl md5 | cut -d' ' -f2) # 计算HA2:MD5(请求方法:请求路径) HA2=$(echo -n "POST:/config/timeofuse" | openssl md5 | cut -d' ' -f2) # 生成随机cnonce(示例用固定值,实际可生成随机字符串) CNONCE="abc123" # 请求计数,首次请求用00000001 NC="00000001" # 计算最终响应值 RESPONSE=$(echo -n "$HA1:6463d513:3927ccc8e06b0a9d4ec28f0bc9d863bc:$NC:$CNONCE:auth:$HA2" | openssl md5 | cut -d' ' -f2)
构造Curl请求:
curl -X POST http://xxx/config/timeofuse \ -H "Content-Type: application/json" \ -H 'Authorization: Digest username="user", realm="Webinterface area", nonce="6463d513:3927ccc8e06b0a9d4ec28f0bc9d863bc", uri="/config/timeofuse", qop=auth, nc=00000001, cnonce="abc123", response="'$RESPONSE'", algorithm=MD5' \ -d '{}'
方法2:通过代理修改响应头
使用中间代理拦截服务器响应,将X-WWW-Authenticate头替换为标准的WWW-Authenticate,让Curl自动处理认证流程。
比如用mitmproxy实现:
- 创建代理脚本
modify_auth_header.py:
from mitmproxy import http def response(flow: http.HTTPFlow) -> None: if flow.response.status_code == 401: if "X-WWW-Authenticate" in flow.response.headers: auth_value = flow.response.headers.pop("X-WWW-Authenticate") flow.response.headers["WWW-Authenticate"] = auth_value
- 启动mitmproxy并加载脚本:
mitmproxy -s modify_auth_header.py
- 通过代理发起Curl请求:
curl -x http://localhost:8080 -u user:your_password -X POST http://xxx/config/timeofuse -H "Content-Type: application/json" -d '{}'
内容的提问来源于stack exchange,提问作者Alram Lechner
相关产品推荐
相关产品推荐

