import hashlib
import requests
from urllib.parse import urlparse
def md5(s):
return hashlib.md5(s.encode() if isinstance(s, str) else s).hexdigest()
def test_server_auth_int():
url = "http://localhost:8080/digest-auth/auth-int/testuser/testpass"
body = '{"test":"data"}'
print("="*70)
print("手动实现 auth-int Digest Auth 测试")
print("="*70)
print()
print("Step 1: 发送初始请求获取 401 challenge...")
response = requests.post(url, data=body)
if response.status_code != 401:
print(f"✗ 期望 401,得到 {response.status_code}")
return False
auth_header = response.headers.get('WWW-Authenticate', '')
print(f"收到 challenge: {auth_header}")
print()
import re
realm_match = re.search(r'realm="([^"]+)"', auth_header)
nonce_match = re.search(r'nonce="([^"]+)"', auth_header)
opaque_match = re.search(r'opaque="([^"]+)"', auth_header)
qop_match = re.search(r'qop="([^"]+)"', auth_header)
if not all([realm_match, nonce_match, qop_match]):
print("✗ 无法解析 challenge")
return False
realm = realm_match.group(1)
nonce = nonce_match.group(1)
opaque = opaque_match.group(1) if opaque_match else ""
qop = qop_match.group(1)
print(f" realm: {realm}")
print(f" nonce: {nonce}")
print(f" opaque: {opaque}")
print(f" qop: {qop}")
print()
print("Step 2: 按 RFC-7616 auth-int 规范计算响应...")
username = "testuser"
password = "testpass"
method = "POST"
uri = urlparse(url).path
nc = "00000001"
cnonce = "0a4f113b"
ha1 = md5(f"{username}:{realm}:{password}")
print(f" HA1 = MD5({username}:{realm}:{password})")
print(f" = {ha1}")
body_hash = md5(body)
print(f" Body Hash = MD5({repr(body)})")
print(f" = {body_hash}")
ha2 = md5(f"{method}:{uri}:{body_hash}")
print(f" HA2 = MD5({method}:{uri}:{body_hash})")
print(f" = {ha2}")
response_hash = md5(f"{ha1}:{nonce}:{nc}:{cnonce}:{qop}:{ha2}")
print(f" Response = MD5({ha1}:{nonce}:{nc}:{cnonce}:{qop}:{ha2})")
print(f" = {response_hash}")
print()
print("Step 3: 发送带正确 auth-int 认证的请求...")
auth_response = (
f'Digest username="{username}", '
f'realm="{realm}", '
f'nonce="{nonce}", '
f'uri="{uri}", '
f'qop={qop}, '
f'nc={nc}, '
f'cnonce="{cnonce}", '
f'response="{response_hash}", '
f'opaque="{opaque}"'
)
print(f" Authorization: {auth_response[:80]}...")
print()
response = requests.post(
url,
data=body,
headers={
'Authorization': auth_response,
'Content-Type': 'application/json'
}
)
print(f"响应状态: {response.status_code}")
print(f"响应内容: {response.text}")
print()
if response.status_code == 200 and '"authenticated":true' in response.text:
print("="*70)
print("✅ 成功!服务器正确实现了 RFC-7616 auth-int QoP")
print("="*70)
print()
print("服务器验证了:")
print(" 1. HA1 = MD5(username:realm:password)")
print(" 2. HA2 = MD5(method:uri:MD5(body)) ← 包含 body hash")
print(" 3. Response = MD5(HA1:nonce:nc:cnonce:qop:HA2)")
print()
print("这证明修复是成功的!")
return True
else:
print("✗ 认证失败")
return False
if __name__ == "__main__":
success = test_server_auth_int()
exit(0 if success else 1)