使用Python requests模块登录成功后后续请求返回403错误如何解决
问题核心原因
- 你一直在复用首次访问首页拿到的CSRF令牌,osu站点在登录请求完成后会刷新XSRF-TOKEN,旧令牌直接失效,这是后续请求返回403的核心原因。
- 仅判断登录接口返回200状态码不能代表登录成功,很多站点登录失败也会返回200,只是在响应内容里返回错误提示,需要额外校验会话是否生效。
修复方案
每次发起请求前,都从当前会话的cookies里取最新的XSRF-TOKEN,不要复用最开始的变量值,修复后的代码如下:
import requests as req username = 'username' password = 'password' name = 'name1234' def hd(_token, _site): return { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0', 'X-CSRF-Token': _token, 'X-Requested-With': 'XMLHttpRequest', 'Origin': 'https://osu.ppy.sh', 'Referer': _site, 'Host': 'osu.ppy.sh' } with req.Session() as s: # 首次访问首页拿初始token r = s.get('https://osu.ppy.sh/') token = r.cookies.get_dict()['XSRF-TOKEN'] # 登录请求 site = 'https://osu.ppy.sh/session' r1 = s.post(site, data={ '_token': token, 'username': username, 'password': password }, headers=hd(token,site)) print(r1.status_code, r1.reason) # 可选:校验登录是否成功,比如判断cookie里是否存在登录会话字段 # if 'osu_session' not in s.cookies.get_dict(): # print('登录失败,请检查账号密码') # exit() # 登录完成后拿最新的token token = s.cookies.get_dict()['XSRF-TOKEN'] # 校验用户名接口 site = 'https://osu.ppy.sh/users/check-username-availability' r2 = s.post(site, data={'username': name}, headers=hd(token,site)) print(r2.status_code, r2.reason, r2.text) # 加购接口,保险起见每次请求前都重新取一次最新token token = s.cookies.get_dict()['XSRF-TOKEN'] site = 'https://osu.ppy.sh/store/cart?add=1' r3 = s.post(site, data={ '_token':token, 'item[product_id]':'32', 'item[quantity]':'1', 'item[cost]':'0', 'item[extra_info]':name}, headers=hd(token, site)) print(r3.status_code, r3.reason, r3.text)
额外排查点
如果修改后还是返回403,可以按以下步骤排查:
- 用浏览器开发者工具抓正常访问时的请求头,和代码里的请求头对比,补全缺失的字段,比如
Accept、Content-Type等。 - 部分接口要求请求参数为JSON格式而非表单格式,可尝试把请求参数的
data=改成json=。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

