首页 > 解决方案 > [Digest Auth]:邮递员或带有自定义标头的请求,都可以;python3-requests(2.14.2) 失败

问题描述

我发送一个 POST 请求以注册到我的网站。

我使用邮递员,我得到 200 好

我自己发送了两次 POST 请求,使用自定义标头,我也得到 200 ok

当我使用 python3 包(请求)时,我得到 401。

以下是步骤:

  1. 我已经定义了一个函数来计算 md5 和自定义标题:

    import re 
    import hashlib
    
    def md5_utf8(x):
        if isinstance(x, str):
            x = x.encode('utf-8')
        return hashlib.md5(x).hexdigest()
    
    
    def make_digest_auth_headers(my_auth, uri):
        nonce = re.findall(r'nonce="(.*?)"', my_auth)[0]
        realm = re.findall(r'realm="(.*?)"', my_auth)[0]
        qop = re.findall(r'qop="(.*?)"', my_auth)[0]
    
        uri = uri
        method = "POST"
        nc = "00000001"
        cnonce = "0a4f113b"
        username = "my_user"
        pwd = "my_pwd"
        # cal HA1
        HA1 = md5_utf8(username + ":" + realm + ":" + pwd)
        # cal HA2
        HA2 = md5_utf8(method + ":" + uri)
        # cal client response
        response = md5_utf8(HA1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + HA2)
    
        headers = {
            "Content-Type": "application/json;charset=utf-8",
            "HOST": "ip:port",
            "Accept": "application/json;charset=utf-8",
            "Accept-Encoding": "gzip, deflate",
            "Connection": "keep-alive",
            "cache-control": "no-cache",
            "Authorization": 'Digest username="' + username + '", realm="' + realm
                             + '", nonce="' + nonce + '", uri="' + uri
                             + '", algorithm=MD5, response="' + response + '", qop='
                             + qop + ', nc=' + nc + ', cnonce="' + cnonce + '"'
        }
    
        return headers
    
  2. 我发送了一个这样的 POST 请求。

import requests
session = requests.Session()
session.headers = {
                "Content-Type": "application/json;charset=utf-8",
                "Accept": "application/json;charset=utf-8"
            }

uri = "/System/Register"

data = {
            "RegisterObject": {
                "DeviceID": my_id
            }
        }

r = session.post('http://my_ip:my_port/System/Register', json=data)
headers = make_digest_auth_headers(r.headers['WWW-Authenticate'], uri)
r = self.session.post(f'{url}/VIID/System/Register', json=data, headers=headers)
print(r.json())
  1. 我得到了 200 好的响应
{'ResponseStatusObject': {'Id': 'my_id',
                          'LocalTime': '20190122090110',
                          'RequestURL': 'http://ip:port/System/Register',
                          'StatusCode': 0,
                          'StatusString': 'OK'}}
  1. 我使用 python3 请求:
import requests
from requests.auth import HTTPDigestAuth

session = requests.Session()
session.auth = HTTPDigestAuth(my_user, my_pwd)
session.headers = {
            "Content-Type": "application/json;charset=utf-8",
            "Accept": "application/json;charset=utf-8"
        }

data = {
            "RegisterObject": {
                "DeviceID": my_id
            }
        }
session.post('http://ip:port/System/Register', json=data)
  1. 我得到了 401:
{'ResponseStatusObject': {'Id': 'my_id',
                          'LocalTime': '20190122090110',
                          'RequestURL': 'http://ip:port/System/Register',
                          'StatusCode': 104,
                          'StatusString': 'Failed'}}

我不知道为什么?这么奇怪。谢谢。

标签: pythonpython-requestsdigest-authentication

解决方案


推荐阅读