You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用curl --ntlm时,NTLM二次认证流程及脚本实现疑问

NTLM认证:从401到200的交互细节

你给出的请求流程对应NTLM认证的核心交互阶段,具体每一步的逻辑如下:

  • 客户端发送第一个NTLM头:这个是NTLM的协商消息(Negotiate Message),由用户名和密码生成,只要账号密码不变,这个值就固定。它的作用是向服务器声明“我支持NTLM认证,请求开启协商”。
  • 服务器返回401及质询头:服务器返回的WWW-Authenticate: NTLM xxxxxxx中的xxxxxxx是质询消息(Challenge Message),包含服务器生成的随机挑战值(nonce)、域名、服务器标识等关键数据——这是客户端生成最终认证消息的核心输入。
  • 客户端发送第二个NTLM头:客户端拿到质询消息后,会用密码的NTLM哈希与质询中的nonce进行加密运算,生成认证消息(Authenticate Message)(也就是你看到的更长的那个NTLM值)。服务器验证这个加密结果的有效性,通过后就返回200 OK。
脚本实现:复用协商头生成认证头

直接把服务器的质询头当作客户端的认证头肯定不行,两者的结构和用途完全不同。下面是具体的实现思路(以Python为例):

步骤1:发送固定协商头,获取服务器质询

先复用你已有的固定NTLM协商头发起请求,提取服务器返回的质询内容:

import requests

# 你的固定NTLM协商值
negotiate_token = "xxxxxxxx"
target_url = "你的目标API/页面URL"

# 发送第一个请求,获取质询
first_resp = requests.get(target_url, headers={"Authorization": f"NTLM {negotiate_token}"})
# 提取质询消息(注意处理头不存在的异常情况)
challenge_token = first_resp.headers["WWW-Authenticate"].split("NTLM ")[1]

步骤2:基于质询生成认证消息

使用NTLM认证库(比如ntlm-auth)来处理加密逻辑,避免手动实现复杂的NTLM算法:

from ntlm_auth import ntlm

# 你的账号信息
username = "你的用户名"
password = "你的密码"
domain = "你的域名(无则留空字符串)"

# 解析服务器的质询消息
challenge = ntlm.Ntlm.parse_challenge_message(challenge_token)
# 生成最终的NTLM认证消息
auth_message = ntlm.Ntlm.create_authenticate_message(
    username, password, domain, challenge
)
# 转换为可用于请求头的字符串
auth_token = auth_message.decode("utf-8")

步骤3:发送带认证头的请求

用生成的认证头发起请求,即可完成认证:

final_resp = requests.get(target_url, headers={"Authorization": f"NTLM {auth_token}"})
print(final_resp.status_code)  # 预期返回200

关键注意事项

  • 若无法使用第三方库,需要手动实现NTLM的核心逻辑:包括计算密码的NTLM哈希、用哈希加密服务器nonce、构造认证消息的二进制结构——这部分逻辑复杂,容易出错,优先推荐使用成熟库。
  • 确保账号拥有目标资源的访问权限,否则即使认证头正确,也可能返回403。

内容的提问来源于stack exchange,提问作者notreallyanengineer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 12:45:36