使用来自 SAML 令牌的 FedAuth cookie 调用 UI 控制器

Call a UI controller with FedAuth cookie from SAML token

我们正在尝试使一些集成测试自动化。因此,我们希望能够以编程方式调用 UI 控制器,以便与卷轴用户所做的一样。出于不同的原因,我们不想使用 UI 测试套件。

问题是我们使用 SSO Windows 身份验证与 WIF 的 WS 联合安全。在配置中,我们使用 passiveRedirectEnabled="true" 以便每次会话 cookie 不存在、无效或过期时,页面都会重定向到 AD FS STS 端点 ("/adfs/ls/")。结果再次重定向回 Web.config 文件中 "reply" 属性指定的页面。

当我查看 Fiddler 时,我清楚地看到第二个重定向(从 AD FS STS 返回)具有 302 状态 returns 对浏览器的 "Set-Cookie : FedAuth=77u/PD94bWwg..." 指令。使用 FedAuth cookie 调用回复页面,一切正常。

有没有办法模拟这种行为并能够使用正确的 FedAuth cookie 调用 UI 控制器?请不要使用 SharePoint,这与它无关。

我终于能够重现我在 Fiddler 中看到的步骤来模仿浏览器。我会把代码放在这里,希望它能对你们中的一些人有所帮助。它不是很干净,它更像是一种 POC 模式,但它仍然可以提供帮助。请注意,在某些请求中我不得不允许自动重定向,而另一些请求我不得不阻止它。

感谢我的同事 Dominique Pothier,他在这方面帮助了我很多。

//First request to the secured site
        var request =
            (HttpWebRequest)WebRequest.Create("https://mysite.mycompany.ca/");
        request.Method = "GET";
        request.UseDefaultCredentials = true;
        request.PreAuthenticate = true;
        request.AllowAutoRedirect = false;

        var httpResponse = (HttpWebResponse)request.GetResponse();

//Redirects to the STS based on the response from the first call, posting the ws-federations infos along
        request =
            (HttpWebRequest)WebRequest.Create(httpResponse.Headers["Location"]);

        request.UseDefaultCredentials = true;
        request.PreAuthenticate = true;
        request.Host = "sts.mycompany.ca";
        request.AllowAutoRedirect = true;
        request.UserAgent =
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36";
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";

        var nameValueCollection = new NameValueCollection { { "Cache-Control", "max-age=0" } };
        request.Headers.Add(nameValueCollection);
        nameValueCollection = new NameValueCollection { { "Upgrade-Insecure-Requests", "1" } };
        request.Headers.Add(nameValueCollection);
        nameValueCollection = new NameValueCollection { { "Accept-Encoding", "gzip, deflate, sdch" } };
        request.Headers.Add(nameValueCollection);
        nameValueCollection = new NameValueCollection { { "Accept-Language", "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4" } };
        request.Headers.Add(nameValueCollection);

        httpResponse = (HttpWebResponse)request.GetResponse();


//Parse the response to get ws-federation infos
        var responseStream = new StreamReader(httpResponse.GetResponseStream());
        var responseData = responseStream.ReadToEnd();
        var xmlReader = XmlReader.Create(new StringReader(responseData));


        var wa = "";
        var wresult = "";
        var wctx = "";

        while (xmlReader.Read())
        {
            if (xmlReader.GetAttribute("name") == "wa")
                wa = xmlReader.GetAttribute("value");
            if (xmlReader.GetAttribute("name") == "wresult")
                wresult = xmlReader.GetAttribute("value");
            if (xmlReader.GetAttribute("name") == "wctx")
                wctx = xmlReader.GetAttribute("value");
        }

        httpResponse.Close();

//Redirects to the controller method we want to hit
        request =
            (HttpWebRequest)WebRequest.Create("https://mysite.mycompany.ca/Home/GetStates");
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.AllowAutoRedirect = false;
        //Add the cookie container to the response so that we can get the FedAuth cookie after the response
        request.CookieContainer = new CookieContainer();

        //Add the ws-federation infos from the last http request to the body of the new request
        using (var streamWriter = new StreamWriter(request.GetRequestStream()))
        {

            if (wa != null)
            {
                var waEncoded = HttpUtility.UrlEncode(wa);
                var wresultEncoded = HttpUtility.UrlEncode(wresult);
                var wctxEncoded = HttpUtility.UrlEncode(wctx);
                var urlEncoded = "wa=" + waEncoded + "&wresult=" + wresultEncoded + "&wctx=" + wctxEncoded;

                streamWriter.Write(urlEncoded);
                streamWriter.Flush();
                streamWriter.Close();
            }
        }
        request.Referer = httpResponse.ResponseUri.OriginalString;

        httpResponse = (HttpWebResponse)request.GetResponse();
        var cookieContainer = request.CookieContainer;

//Use the FedAuth cookie that we got from last http call and add it to a new request to the controller and voila !
        request =
            (HttpWebRequest)WebRequest.Create("https://mysite.mycompany.ca/Home/GetStates");
        request.Method = "GET";
        nameValueCollection = new NameValueCollection { { "X-Requested-With", "XMLHttpRequest" } };
        request.Headers.Add(nameValueCollection);
        //Add the FedAuthCookie from last request
        request.CookieContainer = cookieContainer;
        request.Referer = "https://proacces-dev1.universitas.ca/";

        httpResponse = (HttpWebResponse)request.GetResponse();
        responseStream = new StreamReader(httpResponse.GetResponseStream());
        responseData = responseStream.ReadToEnd();

        Console.WriteLine(responseData);
        Console.ReadLine();