我有一个发布请求,我正在尝试使用python中的requests
发送。但是我收到无效的403错误。通过浏览器,请求可以正常工作。
POST /ajax-load-system HTTP/1.1
Host: xyz.website.com
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-GB,en;q=0.5
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Referer: http://xyz.website.com/help-me/ZYc5Yn
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 56
Cookie: csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1
Connection: close
csrf_test_name=a3f8adecbf11e29c006d9817be96e8d4&vID=9999
我在python中尝试的是:
import requests
import json
url = 'http://xyz.website.com/ajax-load-system'
payload = {
'Host': 'xyz.website.com',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'en-GB,en;q=0.5',
'Referer': 'http://xyz.website.com/help-me/ZYc5Yn',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Content-Length': '56',
'Cookie': 'csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1',
'Connection': 'close',
'csrf_test_name': 'a3f8adecbf11e29c006d9817be96e8d4',
'vID': '9999',
}
headers = {}
r = requests.post(url, headers=headers, data=json.dumps(payload))
print(r.status_code)
但是这正在打印403
错误代码。我在这里做错了什么?
我期望返回响应为json:
{"status_message":"Thanks for help.","help_count":"141","status":true}
您正在混淆标头和有效负载,有效负载是未JSON编码。
这些都是标题:
Host: xyz.website.com
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-GB,en;q=0.5
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Referer: http://xyz.website.com/help-me/ZYc5Yn
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 56
Cookie: csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1
Connection: close
其中大多数是自动化的,不需要手动设置。 requests
会根据URL为您设置Host
,Accept
设置为可接受的默认值,在这种情况下很少需要Accept-Language
,除非使用HTTPS,否则Referer
甚至不会被设置或过滤出于隐私方面的考虑,因此网站不再依赖于它的设置,Content-Type
实际上必须反映您的POST
的内容(并且不是JSON!),因此requests
会根据您的调用方式为其进行设置,Content-Length
必须反映实际的内容长度,因此由requests
进行设置,因为它是计算此内容的最佳位置,并且Connection
应该绝对由库处理,因为您不想阻止它发生如果可以的话,有效地重用连接。
充其量您可以设置X-Requested-With
和User-Agent
,但前提是服务器不会接受该请求。 Cookies
标头反映了浏览器保存的cookie的值。通过使用requests Session object对GET
标头中指定的网址(或同一站点上的其他合适的网址)进行初始Referer
请求,您的脚本可以从服务器获取其自己的Cookie集。服务器应在响应上设置cookie,并将这些cookie存储在会话中以在发布请求中重用。使用该机制来获取您自己的CSRF cookie值。
注意Content-Type
标头:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
当您将字典传递给data
函数的requests.post()
关键字时,库将为您将数据编码为与该内容类型完全相同的语言。
实际有效载荷是
csrf_test_name=a3f8adecbf11e29c006d9817be96e8d4&vID=9999
这是csrf_test_name
和vID
这两个字段,它们是payload
词典的一部分。
请注意,csrf_test_name
值与cookie中的csrf_cookie_name
值匹配] >>。这是网站保护自己免受Cross-site forgery attacks攻击的方式,在这种情况下,第三方可能会尝试代表您发布到相同的URL。这样的第三方将无法访问相同的cookie,因此将被阻止。 您的代码需要获取新的cookie;正确的CSRF实施会限制任何CSRF cookie可以重复使用的时间。
所以要使它全部起作用,需要至少
是:进行了长时间的认真思考。考虑与他们联系,并询问他们是否提供API选项。# *optional*, the site may not care about these. If they *do* care, then # they care about keeping out automated scripts and could in future # raise the stakes and require more 'browser-like' markers. Ask yourself # if you want to anger the site owners and get into an arms race. headers = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0', 'X-Requested-With': 'XMLHttpRequest', } payload = { 'vID': 9999, } url = 'http://xyz.website.com/ajax-load-system' # the URL from the Referer header, but others at the site would probably # also work initial_url = 'http://xyz.website.com/help-me/ZYc5Yn' with requests.Session() as session: # obtain CSRF cookie initial_response = session.get(initial_url) payload['csrf_test_name'] = session.cookies['csrf_cookie_name'] # Now actually post with the correct CSRF cookie response = session.post(url, headers=headers, data=payload)
如果仍然引起问题,则需要尝试另外两个标头
Accept
和Accept-Language
。考虑到这将意味着该站点已经对如何保持自动站点刮板out