У меня есть арендатор Exchange с Microsoft (company.onmicrosoft.com), учетная запись администратора ([email protected]) и страница администрирования, через которую я управляю моей (настройки).
В последнее время существует проект, который я взял для автоматического анализа некоторых веб-данных с страницы администрирования через С#. Я прочитал много статей, связанных с SharePoint, и прочитал их в файлах STS, SRF и активных/пассивных службах федерации.
Итак, давайте перейдем к нему:
Я начал с https://login.microsoftonline.com/login.srf, но с Fiddler понял, что я мог бы просто перейти к https://login.microsoftonline.com/ppsecure/post.srf и достичь того же результата.
Итак, я перехожу к login, введите свои учетные данные, а затем пересылает мне страницу администратора. Достаточно просто, правильно?
Итак, я решил реплицировать сетевой трафик и полагался на следующие сообщения и примеры:
- http://allthatjs.com/2012/03/28/remote-authentication-in-sharepoint-online/
- http://garymcallisteronline.blogspot.co.uk/2012/11/claims-explained.html
- http://www.wictorwilen.se/post/how-to-do-active-authentication-to-office-365-and-sharepoint-online.aspx
- http://blogs.msdn.com/b/cjohnson/archive/2011/05/03/authentication-with-sharepoint-online-and-the-client-side-object-model.aspx
- http://blogs.msdn.com/b/cjohnson/archive/2011/05/14/part-2-headless-authentication-with-sharepoint-online-and-the-client-side-object-model.aspx
На всех этих веб-сайтах есть отличные примеры С# на экранной проверке подлинности, ADFS и кучей другой полезной информации. Проблема в том, что все это для SharePoint.
Итак, я смешал и сопоставил код и придумал следующее:
static void Main3()
{
CookieContainer cookies = new CookieContainer();
//using Bungie example from http://stackoverflow.com/info/2508656/logging-into-a-site-that-uses-live-com-authentication
//Uri url = new Uri("https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1268167141&rver=5.5.4177.0&wp=LBI&wreply=http:%2F%2Fwww.bungie.net%2FDefault.aspx&id=42917");
Uri url = new Uri("https://portal.microsoftonline.com/");
HttpWebRequest http = (HttpWebRequest)HttpWebRequest.Create(url);
http.Timeout = 30000;
http.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
http.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
http.AllowAutoRedirect = false;
http.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http.Headers.Add("Accept-Encoding", "gzip, deflate"); //this option creates the two cookies but loads garbage HTML. Removing this option allows the HTML to load normally
http.KeepAlive = true;
http.CookieContainer = new CookieContainer();
http.Method = WebRequestMethods.Http.Get;
HttpWebResponse response = (HttpWebResponse)http.GetResponse();
//gets the cookies (they are set in the eighth header)
string[] strCookies = response.Headers.GetValues(8);
response.Close();
Cookie manualCookie;
string sManualCookiesString = "MSPRequ|lt=1389810702&id=271346&co=1;MSPOK|$uuid-02eeaf29-b8a5-441f-a6a6-319ed926d8bc$uuid-7f106156-1398-405f-83e5-61f177c7be25$uuid-3d2f189d-8f79-4216-97cf-23c5c22ff8ad$uuid-b93c9354-5802-4c82-ac7d-7838d2f7bdbc$uuid-071c3106-1c97-4e1e-930c-36f33b6f0b93; MSPShared|1; MSPSoftVis|@:@; MSPBack|1389810501";
//Manually insert the cookies since the request only returns two cookies and we need six cookies
foreach (string sCookieAndValue in sManualCookiesString.Split(';'))
{
string sCookieName = sCookieAndValue.Split('|')[0].Trim();
string sCookieValue = sCookieAndValue.Split('|')[1].Trim();
manualCookie = new Cookie(sCookieName, "\"" + sCookieValue + "\"");
Uri manualURL = new Uri("http://login.microsoftonline.com");
http.CookieContainer.Add(manualURL, manualCookie);
}
/* //Removed because the above request only returns MSPRequ and MSPOK cookies but leaves out the others. It obviously broken :(
string name, value;
for (int i = 0; i < strCookies.Length; i++)
{
name = strCookies[i].Substring(0, strCookies[i].IndexOf("="));
value = strCookies[i].Substring(strCookies[i].IndexOf("=") + 1, strCookies[i].IndexOf(";") - strCookies[i].IndexOf("=") - 1);
manualCookie = new Cookie(name, "\"" + value + "\"");
Uri manualURL = new Uri("http://login.microsoftonline.com");
//http.CookieContainer.Add(manualURL, manualCookie);
}
*/
//stores the cookies to be used later
cookies = http.CookieContainer;
http = (HttpWebRequest)HttpWebRequest.Create(url);
response = (HttpWebResponse)http.GetResponse();
StreamReader readStream = new StreamReader(response.GetResponseStream());
string HTML = readStream.ReadToEnd();
readStream.Close();
//Get the PPSX value: these values are a bit strange and could indicate progress since I've seen a few of the following:
// P, Pa, Pas, Pass, Passp, Passpo, Passport, PassportRN
// As you can see it adds one letter at a time which could indicate where in the login process it is, but I don't know
string PPSX = HTML.Remove(0, HTML.IndexOf("PPSX"));
PPSX = PPSX.Remove(0, PPSX.IndexOf("value") + 7);
PPSX = PPSX.Substring(0, PPSX.IndexOf("\""));
//PPSX = "PassP"; //debug
//Get this random PPFT value
string PPFT = HTML.Remove(0, HTML.IndexOf("PPFT"));
PPFT = PPFT.Remove(0, PPFT.IndexOf("value") + 7);
PPFT = PPFT.Substring(0, PPFT.IndexOf("\""));
//Get the random URL you POST to
//string POSTURL = HTML.Remove(0, HTML.IndexOf("https://login.microsoftonline.com/ppsecure/post.srf?wa=wsignin1.0&rpsnv=2&ct="));
//POSTURL = POSTURL.Substring(0, POSTURL.IndexOf("\""));
//debug:
//based on Fiddler, this page is the next page that loaded
string POSTURL = "https://login.microsoftonline.com/GetUserRealm.srf?login=admin%company.onmicrosoft.com&handler=1&extended=1 ";
//POST with cookies
HttpWebRequest http2 = (HttpWebRequest)HttpWebRequest.Create(POSTURL);
//http.AllowAutoRedirect = false;
http2.Accept = "application/json, text/javascript, */*; q=0.01";
http2.Headers.Add("Accept-Encoding", "gzip, deflate");
http2.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http2.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
//http.ContentLength = 0;
http2.KeepAlive = true;
http.CookieContainer = cookies;
http2.Referer = "https://login.microsoftonline.com/ppsecure/post.srf";
http2.Method = WebRequestMethods.Http.Post;
Stream ostream = http2.GetRequestStream();
//used to convert strings into bytes
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
//Post information found via Fiddler. Values have been altered for anonymity
byte[] buffer = encoding.GetBytes(
"login=" + sUsername
+ "&passwd=" + sPassword
+ "&PPSX=" + PPSX
+ "&PPFT=" + PPFT
+ "&n1=107313"
+ "&n2=-1389941230500"
+ "&n3=-1389941230500"
+ "&n4=112373"
+ "&n5=112373"
+ "&n6=112373"
+ "&n7=112373"
+ "&n8=NaN"
+ "&n9=112373"
+ "&n10=112360"
+ "&n11=112358"
+ "&n12=112323"
+ "&n13=112324"
+ "&n14=112396"
+ "&n15=26"
+ "&n16=11239"
+ "&n17=112369"
+ "&n18=112315"
+ "&n19=880.9711230112345"
+ "&n20=1"
+ "&n21=1"
+ "&n22=1381236981084.398"
+ "&n23=1"
+ "&n24=46.789501123103664"
+ "&n25=0"
+ "&n26=0"
+ "&n27=0"
+ "&n28=0"
+ "&n29=-1318912363023"
+ "&n30=-1318912363023"
+ "&n31=false"
+ "&n32=false"
+ "&type=11"
+ "&LoginOptions=3" //this is 2 sometimes
+ "&NewUser=1"
+ "&idsbho=1"
+ "&PwdPad="
+ "&sso="
+ "&vv="
+ "&uiver=1"
+ "&i12=1"
+ "&i13=Firefox"
+ "&i14=26.0"
+ "&i15=1480"
+ "&i16=964"
);
ostream.Write(buffer, 0, buffer.Length);
ostream.Close();
HttpWebResponse response2 = (HttpWebResponse)http.GetResponse();
readStream = new StreamReader(response2.GetResponseStream());
HTML = readStream.ReadToEnd();
response2.Close();
ostream.Dispose();
foreach (Cookie cookie in response2.Cookies) //this returns no cookies
{
Console.WriteLine(cookie.Name + ": ");
Console.WriteLine(cookie.Value);
Console.WriteLine(cookie.Expires);
Console.WriteLine();
}
POSTURL = "https://login.microsoftonline.com/ppsecure/post.srf?bk=1389198967";
//POST with cookies
http = (HttpWebRequest)HttpWebRequest.Create(POSTURL);
http.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
http.AllowAutoRedirect = false;
http.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
http.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http.KeepAlive = true;
http.CookieContainer = cookies;
http.Referer = "https://login.microsoftonline.com/ppsecure/post.srf";
http.Method = WebRequestMethods.Http.Post;
ostream = http.GetRequestStream();
//used to convert strings into bytes
encoding = new System.Text.ASCIIEncoding();
//Post information
ostream.Write(buffer, 0, buffer.Length);
ostream.Close();
HttpWebResponse response3 = (HttpWebResponse)http.GetResponse();
readStream = new StreamReader(response3.GetResponseStream());
HTML = readStream.ReadToEnd();
response3.Close();
ostream.Dispose();
foreach (Cookie cookie in response3.Cookies) //sadly this returns no cookies when it should have 18 cookies in addition to a bunch of BOX.CacheKey cookies
{
Console.WriteLine(cookie.Name + ": ");
Console.WriteLine(cookie.Value);
Console.WriteLine(cookie.Expires);
Console.WriteLine();
}
}
Кто-нибудь знает, как работает сайт, чтобы дать некоторые рекомендации о том, где я терпит неудачу? На веб-сайте также используется JavaScript для создания файлов cookie (вы можете перейти на первую страницу и ввести произвольный адрес, и вы увидите, что некоторые точки перемещаются слева направо в поле имени пользователя.
Возможно, я принимаю неправильный подход, но любая помощь будет оценена по достоинству. Я могу предоставить сводный журнал сеансов Fiddler, если это необходимо.
Спасибо!
P.S. Извините за все замены .com для фактического символа периода, но у меня недостаточно очков репутации. Просто найдите [dot] com и замените на .com, чтобы отменить.