aiohttp请求URL转义异常导致403错误问题排查
问题解决:aiohttp请求返回403,requests正常的原因与修复
问题背景
使用aiohttp库发送请求时返回403错误,但相同URL用requests库或浏览器访问可正常响应。抓包对比发现,两者请求头和参数几乎一致,仅x-signature参数存在差异:
- requests发送的参数:
x-signature=c52PtqjdBH%2FkUluVO79XQpC1fnw%3D - aiohttp发送的参数:
x-signature=c52PtqjdBH/kUluVO79XQpC1fnw%3D
aiohttp自动将URL中已转义的%2F还原为/,这是导致服务器签名校验失败、返回403的核心原因。
原因分析
aiohttp基于yarl库处理URL,默认会对URL进行规范化操作,其中包括解码已转义的斜杠%2F。而requests库则保留了URL中的原始转义字符,不会自动解码。由于x-signature是服务器生成的签名参数,其中的%2F是签名的一部分,一旦被解码为/,服务器端的签名验证就会失败,从而返回403 Forbidden。
解决方案
通过yarl库手动构造URL,关闭自动解码%2F的功能,确保请求中的x-signature参数与原始URL完全一致:
import asyncio import aiohttp from yarl import URL async def main(): # 使用encoded=True保留URL中的原始转义字符 target_url = URL( 'http://p3-pc-sign.douyinpic.com/tos-cn-i-0813/dd367e76c9ea41ab9ee43b8f171e45aa~tplv-dy-aweme-images:q75.webp?x-expires=1691013600&x-signature=c52PtqjdBH%2FkUluVO79XQpC1fnw%3D&from=3213915784&s=PackSourceEnum_PUBLISH&se=false&sc=image&biz_tag=aweme_images&l=20230720060500934814BD78FB30518EED', encoded=True ) async with aiohttp.ClientSession() as session: async with session.get(target_url, headers={ 'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'close' }) as resp: print(resp.headers['Content-Type']) print(await resp.text()) asyncio.run(main())
验证效果
修改后,aiohttp发送的请求会完整保留x-signature中的%2F转义字符,与requests和浏览器的请求一致,服务器端的签名校验将通过,返回正常响应。
内容的提问来源于stack exchange,提问作者user13082750
相关产品推荐
相关产品推荐

