Python POST请求返回404状态代码,但GET请求返回200

时间:2020-02-11 18:48:45

标签: python python-3.x python-requests

我正在尝试登录this网站。当我提交一个简单的GET请求时,得到了200个预期的响应。

import requests

login_url = 'https://urs.earthdata.nasa.gov/'

sess = requests.Session()
sess.headers ={'User-Agent':'Mozilla/5.0'}
sess.verify=False
r1 = sess.get(login_url)
print (r1.status_code)
>>>200

但是,当我尝试使用POST请求实际登录时,出现404错误。 (请求的有效负载是从该页面的html并使用Firefox中的页面检查器获得的。)

import requests
import re

product_url = 'https://datapool.asf.alaska.edu/L1.5/A3/ALPSRP171431190-L1.5.zip'
login_url = 'https://urs.earthdata.nasa.gov/'
username = 'username'
password = 'password'

sess = requests.Session()
sess.headers ={'User-Agent':'Mozilla/5.0'}
sess.verify=False

r1 = sess.get(product_url)

tkn_ptn = '<meta name="csrf-token" content="(.*==)" />'
tkn = re.search(tkn_ptn,r1.text).group(1)
print('CSRF Token: {}'.format(tkn))
>>>'CSRF Token: CDOX5tOhBtX2vvZn/c/MLRaYJtW7hzeQLm/eEVn09cHosnlsR/5P8a+k4YEaAzYQZRxCgNf9evDqyhWiZiefmQ=='

cli_ptn = '<input type="hidden" name="client_id" id="client_id" value="(.*)" />'
cli = re.search(cli_ptn,r1.text).group(1)
print('Client ID: {}'.format(cli))
>>>'Client ID: BO_n7nTIlMljdvU6kRRB3g'

redir_ptn = '<input type="hidden" name="redirect_uri" id="redirect_uri" value="(.*?)" />'
redir = re.search(redir_ptn,r1.text).group(1)
print ('Redirect URL: {}'.format(redir))
>>>'Redirect URL: https://auth.asf.alaska.edu/login'

payload = {'username':username, 
            'password':password,
            'authenticity_token' : tkn,
            'client_id' : cli, 
            'redirect_uri': redir,
            'response_type' : 'code', 
            'stay_in' : '1', 
            'commit':'Log in'}

r2 = sess.post(login_url, data=payload)
print (r2.status_code)
>>>404

为什么页面不能接受我的有效载荷并让我登录?

1 个答案:

答案 0 :(得分:1)

有效负载数据来自登录页面本身,因此可以https://urs.earthdata.nasa.gov/查看浏览器上的“网络”标签。
我刚刚输入了一些随机的用户名和密码,然后查看“网络”选项卡,发现对https://urs.earthdata.nasa.gov/login进行了POST。查看有效负载,这是它的格式:

utf8: ✓
authenticity_token: ...token base64...
username: 123
password: 123
client_id: 
redirect_uri: 
commit: Log in

因此,我们只需要从源中提取authenticity_token。在查看登录页面的源代码时,我们看到以下内容:

<form id="login" action="/login" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="...token base64..." />

因此,我们仅使用一些正则表达式来提取此位,因为对于像这样的一次性使用的东西,它更快(您可以使用所需的任何其他方法或正则表达式形式):

token = re.search(r'authenticity_token".*?"(.*?)"', webpage.text).group(1)

最后创建数据并将其传递给POST方法:

data = {
"utf8": "✓",
"authenticity_token": token,
"username": username,
"password": password,
"client_id": "",
"redirect_uri": "",
"commit": "Log in",
}
login = requests.post("https://urs.earthdata.nasa.gov/login", headers={'User-Agent':'Mozilla/5.0'}, data=data)