使用Python requests发送带Basic认证的PUT请求返回400 Bad Request问题排查
你遇到的400错误主要来自两个关键问题,咱们拆解来看:
1. Basic Auth设置冲突
你在代码里同时做了两件矛盾的事:
- 在
headers里手动写了Authorization: 'Basic Token' - 又通过
auth=HTTPBasicAuth('login','password')让requests自动生成Basic认证头
这会直接导致认证混乱!当你使用auth参数时,requests会自动把用户名和密码编码成Basic <base64编码的login:password>格式的字符串,并自动替换掉你手动设置的Authorization头。而你写的'Basic Token'根本不是有效的Basic认证值,这是触发错误的核心原因之一。
其实Postman里的正确操作是:当你选择Basic Auth并填入用户名密码后,Postman会自动生成正确的Authorization头,你手动添加的Authorization: 'Basic Token'其实是多余的——只是Postman优先使用了自动生成的有效认证头,所以请求能正常执行。
2. 请求体格式不匹配
你的请求头明确设置了Content-Type: application/json,但代码里用了data=data参数。data参数在requests里默认会把数据以表单格式(application/x-www-form-urlencoded)发送,哪怕你手动设置了Content-Type头,也需要确保数据是JSON字符串;更省心的方式是改用json=data参数,requests会自动把Python对象序列化为JSON字符串,还能自动匹配Content-Type头(当然你手动设置也没问题)。
修正后的代码
去掉手动设置的Authorization头,同时改用json参数传递请求体:
import requests from requests.auth import HTTPBasicAuth req = requests.put( url, headers={'Content-Type': 'application/json'}, auth=HTTPBasicAuth('login', 'password'), json=data # 替换为json参数 )
如果你不想用auth参数,也可以手动构造正确的认证头(但更推荐用auth参数,避免编码出错):
import requests import base64 # 手动编码用户名和密码 auth_str = f"login:password" base64_auth = base64.b64encode(auth_str.encode('utf-8')).decode('utf-8') req = requests.put( url, headers={ 'Authorization': f'Basic {base64_auth}', 'Content-Type': 'application/json' }, json=data )
这样修改后,请求就和Postman里的逻辑一致了,应该能解决400错误。
内容的提问来源于stack exchange,提问作者Sasha

