使用标准库进行Python HTTP NTLM身份验证

1 投票
1 回答
2746 浏览
提问于 2025-04-18 14:20

我想知道怎么用Python实现HTTP的NTLM认证,而且不想使用第三方的Python NTLM库。

1 个回答

1

只要用户名不是域的一部分,这个方法就能正常工作。在某些情况下,你可能需要用 ntlm='NTLM' 来代替 Negotiate

def ntlm_authenticate_message(nonce, username, password):
    # http://davenport.sourceforge.net/ntlm.html#theLmv2Response
    import hashlib
    import hmac
    import os
    ntlm_hash = hashlib.new('md4', password.encode('utf-16le')).digest()
    ntlm_v2 = hmac.new(ntlm_hash, username.upper().encode('utf-16le')).digest()
    rand = os.urandom(8)
    lm = hmac.new(ntlm_v2, nonce + rand).digest() + rand
    return ('NTLMSSP\0\3\0\0\0' + '\x18\0\x18\0\x40\0\0\0' + '\0' * 8 + '\0' * 8 +
            chr(len(username)) + '\0' + chr(len(username)) + '\0' + '\x58\0\0\0' +
            '\0' * 8 + '\0' * 8 + '\0' * 4 + lm + username).encode('base64').replace('\n', '')


def http_ntlm_auth(url, data, headers, username, password, ntlm='Negotiate'):
    # http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication
    u = urlparse(url)
    h = HTTPSConnection(u.netloc)
    # h.set_debuglevel(1)
    h.request('GET', u.path, None, {'Authorization': ntlm + ' ' + 'NTLMSSP\0\1\0\0\0\2\0\0\0'.encode('base64')})  # 1
    resp = h.getresponse()
    error = resp.read()
    assert resp.status == 401 and not error, (resp.status, resp.reason, error)
    nonce = resp.getheader('WWW-Authenticate').split()[1].decode('base64')[24:32]  # type 2
    headers['Authorization'] = ntlm + ' ' + ntlm_authenticate_message(nonce, username, password)  # type 3
    h.request('POST' if data else 'GET', u.path, data, headers)
    return h.getresponse()

撰写回答