我有一个需要定期访问的网站。从浏览器上看,它运行良好。网站给了我一个15分钟后过期的cookie。如果我在一个小时后返回服务器,它会将我重定向到login.microsoft.com,然后将我重定向回服务器。
我需要在无人值守的电脑上做同样的事情。是否有文档描述了我需要从目标服务器和Microsoft IDP服务器捕获哪些信息,以便在会话cookie超时时允许我的计算机续订身份验证?
为了使用Azure AD IDP进行身份验证,我最终使用了Puppeteer Sharp(控制无头版本的Chromium(和以下功能(逐步完成其pases(进行身份验证。SSOLogin的参数如下:
- 目的地-是驻留在SSO后面的REST API
- 电子邮件-用于进行身份验证的电子邮件地址
- password-与电子邮件地址关联的密码
- 选择器-API中存在的元素选择器
- cookieParams-由API和IDP发送的cookie
最初没有cookie。但是,SSOLogin返回当前的一组cookie。如果API的cookie尚未过期,登录是快速而简单的。如果IDP cookie尚未过期,您将被重定向回API。如果IDP上的cookie已经过期,那么您可以使用电子邮件地址和密码登录。
在任何情况下,您都可以从API中提取Cookie并使用它们进行调用。
使用的Nuget包:
-
微软。AspNet。WebApi。客户端(5.2.7(
-
PuppeteerSharp(5.0.0(
-
系统。网Http。Json(5.0.0(
public static async Task<CookieParam[]> SSOLogin(CookieParam[] cookieParams, string destination, string email, string password, string selector) { var options = new LaunchOptions { Headless = true }; // Set to false to watch browser step through activities var selectorOption = new WaitForSelectorOptions { Visible = true, Timeout = 10000 }; await new BrowserFetcher().DownloadAsync(); // Only needed the first time through using var browser = await Puppeteer.LaunchAsync(options); using var page = await browser.NewPageAsync(); await page.SetCookieAsync(cookieParams); await page.GoToAsync(destination); try { await page.WaitForSelectorAsync($"{selector}, input[name='loginfmt']", selectorOption); } catch (Exception e) { Console.WriteLine($"First page error: {e.Message}"); } var url = page.Url; if (url.StartsWith("https://login.microsoftonline.com/")) { if (await page.QuerySelectorAsync($"div[data-test-id='{email}']") != null) { await page.ClickAsync($"div[data-test-id='{email}']"); } else { await page.WaitForSelectorAsync("input[name='loginfmt']:not(.moveOffScreen)", selectorOption); await page.FocusAsync("input[name='loginfmt']"); await page.Keyboard.TypeAsync(email); await page.WaitForSelectorAsync("input[type=submit]", selectorOption); await page.ClickAsync("input[type=submit]"); } await page.WaitForSelectorAsync("input[type=password]:not(.moveOffScreen)", selectorOption); await page.FocusAsync("input[type=password]"); await page.Keyboard.TypeAsync(password); await page.WaitForSelectorAsync("input[type=submit]", selectorOption); await page.ClickAsync("input[type=submit]"); await page.WaitForSelectorAsync("input[name='DontShowAgain']:not(.moveOffScreen)", selectorOption); await page.ClickAsync("input[name='DontShowAgain']"); await page.WaitForSelectorAsync("input[type=submit]", selectorOption); await page.ClickAsync("input[type=submit]"); await page.WaitForSelectorAsync(selector, selectorOption); } return await page.GetCookiesAsync("https://login.microsoftonline.com/", destination); }