在python中,我经常使用的API要求我使用自己的凭据在浏览器中进行身份验证。
我能够通过查看登录时发送的请求并模仿python中的请求来实现此目的。我写的东西行得通,但是我留下了漫长,令人困惑且未优化的登录方式。登录并获取回调URL大约需要5秒钟,因此我可以使用API进行身份验证。
下面是我的代码。如何改善下面的内容,以便更快更容易阅读?
import requests
from bs4 import BeautifulSoup
from fhirclient import client
def connect(settings, username, password):
'''Connects to the API
'''
smart = client.FHIRClient(settings=settings)
with requests.session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'
# gets login url from auth url
auth_resp = s.get(smart.authorize_url)
login_url = auth_resp.url
# parses login url to get login form values
auth_resp_soup = BeautifulSoup(auth_resp.text, features="html.parser")
login_payload = {
"Username": username,
"Password": password,
'RedirectUrl': auth_resp_soup.find('input', {'name': 'RedirectUrl'}).get('value'),
'SignInId': auth_resp_soup.find('input', {'name': 'SignInId'}).get('value'),
'__RequestVerificationToken': auth_resp_soup.find('input', {'name': '__RequestVerificationToken'}).get('value')
}
# passes login information to login form
login_resp = s.post(login_url, data=login_payload)
consent_url = login_resp.url
# gets redirected to consent screen
consent_red_resp = s.get(consent_url + '?finalRedirectFragment=')
# parses consent redirect page for authorization
consent_red_resp_soup = BeautifulSoup(consent_red_resp.text, features="html.parser")
home_payload = {
'id_token': consent_red_resp_soup.find('input', {'name': 'id_token'}).get('value'),
'scope': consent_red_resp_soup.find('input', {'name': 'scope'}).get('value'),
'state': consent_red_resp_soup.find('input', {'name': 'state'}).get('value'),
'session_state': consent_red_resp_soup.find('input', {'name': 'session_state'}).get('value')
}
# passes authorization info back to homepage
home_resp = s.post('https://homepage.com/Test', data=home_payload)
# parses consent from to hit I agree
home_resp_soup = BeautifulSoup(home_resp.text, features="html.parser")
consent_payload = {
'__RequestVerificationToken': home_resp_soup.find('input', {'name': '__RequestVerificationToken'}).get('value'),
'patientID': home_resp_soup.find('input', {'name': 'patientID'}).get('value'),
'agree': home_resp_soup.find('input', {'name': 'agree'}).get('value')
}
# sends consent back to form and catches the redirects until it hits the call back url
consent_resp = s.post(home_resp.url, data=consent_payload, allow_redirects=False)
callback_resp = s.get(consent_resp.headers['Location'], allow_redirects=False)
callback_url = callback_resp.headers['Location']
smart.handle_callback(callback_url)
return smart