使用Python requests获取CSRF令牌

11

我目前使用Python Requests,并需要一个CSRF token来登录到一个站点。据我的理解,requests.Session()可以获得cookie,但显然我需要token。我也想知道在我的代码中放置它的位置。 import requests

user_name = input('Username:')
payload = {
'username': 'user_name',
'password': 'randompass123'
}


with requests.Session() as s:
p = s.post('https://examplenotarealpage.com', data=payload)

这个网站会很简单地向你介绍整个过程:http://kazuar.github.io/scraping-tutorial/ 基本上,查找页面源代码中名为“csrftoken”或类似名称的输入标签。 - wp78de
3个回答

16

请看以下代码示例。您可以直接使用它来登录只使用cookies存储登录信息的网站。

import requests

LOGIN_URL = 'https://examplenotarealpage.com'
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}

response = requests.get(LOGIN_URL, headers=headers, verify=False)

headers['cookie'] = '; '.join([x.name + '=' + x.value for x in response.cookies])
headers['content-type'] = 'application/x-www-form-urlencoded'
payload = {
    'username': 'user_name',
    'password': 'randompass123'
}

response = requests.post(LOGIN_URL, data=payload, headers=headers, verify=False)
headers['cookie'] = '; '.join([x.name + '=' + x.value for x in response.cookies])

CSRF令牌可能会有几个不同的位置。不同的网站使用不同的方法将其传递给浏览器,以下是其中一些位置:

  • 它可能随着响应头一起返回,在这种情况下获取它很容易。
  • 有时候页面元数据中包含CSRF令牌。您需要解析页面的HTML内容以获取它,并找到正确的CSS选择器。参见下面的示例:

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(response.text, 'lxml')
    csrf_token = soup.select_one('meta[name="csrf-token"]')['content']
    
  • 它可以在带有JavaScript代码的脚本标签内部。获取它会很棘手。但是,您始终可以使用正则表达式来隔离它。


1
谢谢您让我找到正确的方向,我正在尝试向一个网站发送请求,但是我无论如何都无法弄清楚Chrome是如何在未获取X-CSRF令牌的情况下发送它们的。 - Amon

5
import requests
from bs4 import BeautifulSoup
headers = {'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 
           (KHTML, like Gecko) Chromium/80.0.3987.160 Chrome/80.0.3987.163 
           Safari/537.36'
 }
login_data = {
             'name' : 'USERNAME',
             'pass' : 'PASSWORD',
             'form_id':'new_login_form',
             'op':'login'
  }

with requests.Session() as s:
    url = 'https://www.codechef.com/'
    r = s.get(url,headers=headers,verify=False)
    #print(r.content) # to find name of csrftoken and form_build_id
    soup = BeautifulSoup(r.text, 'lxml')

    csrfToken = soup.find('input',attrs = {'name':'csrfToken'})['value']
    form_build_id = soup.find('input',attrs = {'name':'form_build_id'}) 
    ['value']

    login_data['csrfToken'] = csrfToken
    login_data['form_build_id'] = form_build_id

    r = s.post(url,data=login_data,headers = headers)
    print(r.content)

你可以直接使用这个方法,但是有一些需要改变的地方:
1.在浏览器网络选项中检查您的用户代理。
2.通过打印(r.content)来检查您的csrf-token和form_build_id的name属性,并查找csrftoken和form-build-id并检查它们的name属性。

最后一步:

r.content中搜索logout,如果有,则表示您已登录。


安装了"bs4"和"lxml"之后,工作得非常好。使用pip进行安装。 - Cagy79
使用pip安装"bs4"和"lxml"后,工作得非常顺利。 - undefined

0

我把它放在这里是因为我花了很多时间和分析网络交互才找到这个答案...

我必须使用Python/Requests登录到一个Swagger/OpenAPI。我可以用浏览器登录到网站,但是要用Requests登录,我需要x_csrf_token/sails.sid组合...

在尝试并失败了这里和其他地方的所有答案后,我检查了浏览器通信。结果发现唯一的方法是先获取'sails.sid',然后对未记录的(?) /csrfToken进行GET请求...

base_host = '...'
base_path= '/api/v2'
base_url = base_host + base_path
data = {
  "email": "...",
  "password": "..."
}
resp = requests.post(f"{base_url}/login", data=data)
session_cookie = resp.cookies
session_dict=session_cookie.get_dict()

sails_sid = session_dict.get('sails.sid','could not get valid [sails.sid]')
print(f'sails.sid:{[sails_sid]}')

然后:

cookies = {
    'sails.sid': sails_sid,
}
headers = {
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0',
}
r2 = requests.get(f"{base_url}/csrfToken",  cookies=cookies, headers=headers)
print(r2.json())

请注意,在我的情况下,它是电子邮件/密码...我通过使用Firefox检查分析了浏览器,所以这可能也是您的最后选择...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接