我想出了如何做到这一点。
警告:这仅用于一次性控制台应用程序,它允许我们针对 EmbeddedSTS 进行身份验证并执行 WebAPI 调用以进行压力测试。
本质上,我们模拟浏览器上会发生什么。这使用 HttpClient 和 HtmlAgilityPack 解析 HTML 响应,选择用户,将其发布回 EmbeddedSTS,然后发布 WS Fed 令牌结果并最终接收 FedAuth cookie。之后,可以使用 HTTP 客户端调用应用程序中的任何 WebAPI 或 MVC 页面。
public static Task<HttpClient> BuildClient(string authurl, string username)
{
var task = Task.Run<HttpClient>(async () =>
{
// setup http client an cookie handler
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.CookieContainer = new System.Net.CookieContainer();
handler.UseCookies = true;
var client = new HttpClient(handler);
client.MaxResponseContentBufferSize = 256000;
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
client.DefaultRequestHeaders.ExpectContinue = false;
// this is the html of the page that has the user dropdown
var userSelectionPage = await client.GetStringAsync(authurl);
string actionPathAndQuery = GetAction(userSelectionPage);
// for the purposes of this sample, we just choose the user called admin
var postData = new List<KeyValuePair<string, string>>() {
new KeyValuePair<string, string>("username", username)
};
// now we post the user name and expect to get the ws fed response
var wsfedresponse = await client.PostAsync(authurl + actionPathAndQuery, new FormUrlEncodedContent(postData));
var wsfedcontent = await wsfedresponse.Content.ReadAsStringAsync();
var namevaluepairs = GetHiddenInputNameValues(wsfedcontent);
var finalpost = await client.PostAsync(authurl, new FormUrlEncodedContent(namevaluepairs));
// at this point, the fedauth cookie is set, we are good to go
return client;
});
return task;
}
private static string GetAction(string htmlContent)
{
var d = new HtmlDocument();
d.LoadHtml(htmlContent);
var node = d.DocumentNode.SelectSingleNode("//form[@action]");
var result = node.GetAttributeValue("action", string.Empty);
return result;
}
private static IEnumerable<KeyValuePair<string, string>> GetHiddenInputNameValues(string htmlContent)
{
var d = new HtmlDocument();
d.LoadHtml(htmlContent);
var nodes = d.DocumentNode.SelectNodes("//input[@type='hidden']");
return nodes.Select(p =>
new KeyValuePair<string, string>(
p.GetAttributeValue("name", string.Empty),
System.Web.HttpUtility.HtmlDecode(p.GetAttributeValue("value", string.Empty))
));
}