В 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