这完全令人抓狂...我有 OAuth2.0 请求发送到 web 应用程序,并且我想使用 python selenium 检索我的访问令牌。
我尝试使用 rauth、requests 和 oauthlib.oath2 在生成我的 api 密钥后获取访问令牌。 Selenium 是我看到任何结果的唯一途径,所以我可能会完全错过目标。
唯一的亮点就是这个......
Datto API 文档 表示使用 Postman 来获取您的访问令牌令牌。我可以从 python 中执行 API 调用,但这不是一个非常可重复的过程。
Datto 的所有示例也采用了此流程。
如何使用 selenium 或 python 脚本来简单地执行 oauth 检索我的访问令牌,以便我可以在将来的请求中对其进行变量化?
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.alert import Alert
import time
#Oauth2.0 credentials.
client_id = 'public-client'
client_secret = 'public'
# URLs to retrieve tokens
authorize_url = "https://zinfandel-api.centrastage.net/auth/oauth/authorize"
access_token_url = "https://zinfandel-api.centrastage.net/auth/oauth/token"
# This is your API Public Key.
auth_user = 'YOUR_PUBLIC_KEY_HERE'
# This is your API Secret Key.
auth_pass = 'YOUR_SECRET_KEY_HERE'
# This installs the driver that selenium needs to open your browser.
browser = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
#browser.maximize_window()
time.sleep(3)
# This goes to a website.
browser.get(access_token_url)
# Used to download page source code
with open("page_source.html", "w") as f:
f.write(browser.page_source)
f.close()
time.sleep(5)
# A list of all window handles
main_window_handle = browser.window_handles
# Handle of the first window open.
main_window = main_window_handle[0]
# This will switch us to a new window if there is more than one.
# Right now the web app isn't being seen as a window.
for handle in browser.window_handles:
if handle != main_window:
popup = handle
#print(popup)
browser.switch_to.window(popup)
time.sleep(3)
print("Starting anonymous key send.")
actions = ActionChains(browser)
time.sleep(3)
popup_alert = Alert(browser)
print(popup_alert.page_source)
# This will error out because the page isn't an alert.
#browser.switch_to.alert
# Is this an Alert?
#with open("active_elment_alert.html", "w") as f:
# f.write(browser.page_source)
# f.close()
# I'm going to try to switch to a frame and write to it.
browser.switch_to.frame
# If this is a frame we'll see soething here.
with open("active_elment_frame.html", "w") as f:
f.write(browser.page_source)
f.close()
browser.switch_to.active_element
# Used to download active element source code.
# You can see that after I switch I don't see any html other than what was presented earlier.
with open("active_elment_source.html", "w") as f:
f.write(browser.page_source)
f.close()
################## I THINK THIS IS WHERE I NEED HELP ##################
#This is probably just posting nonsense in the empty html body.
# I'm trying to xpath to either a label or anything with the username field.
mystery_field = browser.find_element(By.XPATH,'//*[contains(text(),ernam)]')
#mystery_field = browser.find_element(By.XPATH,"//label[contains(text(),ernam)]")
print(mystery_field.text)
#start_a_doing_stuff = browser.switch_to.frame(mystery_field)
time.sleep(3)
actions.click(mystery_field).perform
time.sleep(3)
actions.send_keys(client_id).perform()
time.sleep(3)
actions.send_keys(Keys.TAB).perform()
time.sleep(3)
actions.send_keys(client_secret).perform()
time.sleep(3)
actions.send_keys(Keys.RETURN).perform()
time.sleep(3)
print("The anonymous key send is done.")
time.sleep(3)
################## I THINK THIS IS WHERE I NEED HELP ##################
# This portion appropriately sends content to authorize url.
#user_name_field = browser.find_element(By.NAME, "username")
#password_field = browser.find_element(By.NAME, "password")
#user_name_field.send_keys(auth_user)
#user_name_field.send_keys(Keys.TAB)
#password_field.send_keys(auth_pass)
#password_field.send_keys(Keys.RETURN)
#actions.perform()
#time.sleep(3)
#When everything is done, this closes your browser.
browser.quit()
当脚本运行时,您可以在用户名字段中看到光标,当您访问该站点时,html 正文为空。
但是,在无法看到任何字段的情况下,我试图在身份验证警报框打开后立即将密钥发送到光标。
我知道硒不会将其视为警报,因为当我尝试将密钥发送到警报元素时,我的代码出错了。
在现代 Web 应用程序中,OAuth 令牌有点难以获取。 用户不会有专用端点来请求 user_credentials 来获得 access_token。
其中一种方法是用户需要手动登录Web应用程序,然后需要获取令牌。 这可以在 Web 自动化中借助 Selenium Dev Tools(版本 > 4)或借助 浏览器代理工具 来实现。 API自动化用户可以启动Headless Browser来获取令牌。
通过 Selenium DevTools 获取令牌:
需要注意的是,通过第三方工具,用户将只能获取 OAuth 令牌的 OPTIONS 请求(不是响应中包含 access_token 的 POST 请求)。
因此,用户需要查找任何特定的 Web 应用程序 API 请求,该请求将包含 与 AUTHERTICATION = Bearer 相同的 access_token。 查找请求标头。
以下代码片段
{
writer = new BufferedWriter(new FileWriter("network_logs.txt", false));
// Add listener for network requests
devTools.addListener(Network.requestWillBeSent(), request -> {
// Store the request in the map
requestMap.put(request.getRequestId().toString(), request);
});
// Add listener for network responses
RequestId[] requestIds = new RequestId[1];
devTools.addListener(Network.responseReceived(), response -> {
try {
requestIds[0] = response.getRequestId();
String requestId = response.getRequestId().toString();
Response res = response.getResponse();
if (requestMap.containsKey(requestId)) {
RequestWillBeSent req = requestMap.get(requestId);
String url = res.getUrl();
// System.out.println(url);
if (url.contains(<USER_WEBAPPLICATION_REQUEST_URL>) && req.getRequest().getMethod().equalsIgnoreCase("POST")) { // Filter for specific endpoint
// Write request details to file
writer.write("\n\t\t=========== NEW REQUEST BEGINS ============ \n");
writer.write("Request URL: " + req.getRequest().getUrl() + "\n");
writer.write("Request Method: " + req.getRequest().getMethod() + "\n");
writer.write("Request Headers: " + req.getRequest().getHeaders() + "\n");
writer.write(
"Request Access Token: " + extractAccessToken(req.getRequest().getHeaders()) + "\n");
writer.write("---------------------------------\n");
// Write response details to file
writer.write("Response URL: " + url + "\n");
writer.write("Response Status: " + res.getStatus() + "\n");
writer.write("Response Headers: " + res.getHeaders() + "\n");
try {
GetResponseBodyResponse responseBody = devTools
.send(Network.getResponseBody(response.getRequestId()));
if (responseBody != null) {
String body = responseBody.getBody();
writer.write("Response Body: " + body + "\n");
} else {
writer.write("Response Body: [No Content]\n");
}
} catch (Exception e) {
writer.write("---> Response Body: Failed to get response body: " + e.getMessage() + "\n");
}
writer.write("\t\t=========== REQUEST ENDS ============\n");
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
// Navigate to a website
try {
driver.get(webURL);
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
loggingMethod(); // POST Logging in, we need to extract token
}