2010-10-27 48 views
1

我正在嘗試編寫一個實用程序,它將嘗試登錄到Microsoft Online Admin網站並報告它是否可以訪問。用C編程式登錄到Microsoft Online網站#

使用代碼主要從這篇文章,http://odetocode.com/articles/162.aspx和一些屏幕抓取我已拼湊在一起以下。不幸的是,它不起作用,最終的反應表明我仍然在看登錄頁面而不是目標頁面。

任何幫助將是了不起的。提前致謝。

private void LoginToSite() 
    { 
     const string LOGIN_URL = "https://admin.microsoftonline.com/Login.aspx"; 
     const string USERNAME = "<username>"; 
     const string PASSWORD = "<password>"; 
     const string TARGET_PAGE_URL = "https://admin.noam.microsoftonline.com/Home/Home.aspx"; 

     // first, request the login form to get the viewstate value 
     HttpWebRequest webRequest = WebRequest.Create(LOGIN_URL) as HttpWebRequest; 
     StreamReader responseReader = new StreamReader(
       webRequest.GetResponse().GetResponseStream() 
      ); 
     string responseData = responseReader.ReadToEnd(); 
     responseReader.Close(); 

     // extract the viewstate value and build out POST data 
     string viewState = ExtractViewState(responseData); 
     string postData = 
       String.Format(
       "__VIEWSTATE={0}&AdminCenterLoginControl$UserNameTextBox={1}&AdminCenterLoginControl$PasswordTextbox={2}&__EVENTTARGET=AdminCenterLoginControl_ActionButton", 
       viewState, USERNAME, PASSWORD 
      ); 

     // have a cookie container ready to receive the forms auth cookie 
     CookieContainer cookies = new CookieContainer(); 

     // now post to the login form 
     webRequest = WebRequest.Create(LOGIN_URL) as HttpWebRequest; 
     webRequest.Method = "POST"; 
     webRequest.ContentType = "application/x-www-form-urlencoded"; 
     webRequest.CookieContainer = cookies; 

     // write the form values into the request message 
     StreamWriter requestWriter = new StreamWriter(webRequest.GetRequestStream()); 
     requestWriter.Write(postData); 
     requestWriter.Close(); 

     // we don't need the contents of the response, just the cookie it issues 
     webRequest.GetResponse().Close(); 

     // now we can send out cookie along with a request for the protected page 
     webRequest = WebRequest.Create(TARGET_PAGE_URL) as HttpWebRequest; 
     webRequest.CookieContainer = cookies; 
     responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()); 

     // and read the response 
     responseData = responseReader.ReadToEnd(); 
     responseReader.Close(); 

     MessageBox.Show(responseData); 
    } 

    private string ExtractViewState(string s) 
    { 
     string viewStateNameDelimiter = "__VIEWSTATE"; 
     string valueDelimiter = "value=\""; 

     int viewStateNamePosition = s.IndexOf(viewStateNameDelimiter); 
     int viewStateValuePosition = s.IndexOf(
       valueDelimiter, viewStateNamePosition 
      ); 

     int viewStateStartPosition = viewStateValuePosition + 
            valueDelimiter.Length; 
     int viewStateEndPosition = s.IndexOf("\"", viewStateStartPosition); 

     return HttpUtility.UrlEncodeUnicode(
       s.Substring(
        viewStateStartPosition, 
        viewStateEndPosition - viewStateStartPosition 
       ) 
      ); 
    } 

編輯

private void LoginToSite() 
    { 
     const string LOGIN_URL = "https://admin.microsoftonline.com/login.aspx?ReturnUrl=%2fDefault.aspx"; 
     const string USERNAME = "<username>"; 
     const string PASSWORD = "<password>"; 

     // Request the login form to get the viewstate value 
     HttpWebRequest webRequest = WebRequest.Create(LOGIN_URL) as HttpWebRequest; 
     string response1 = new StreamReader(webRequest.GetResponse().GetResponseStream()).ReadToEnd(); 

     // Extract the viewstate value and build our POST data 
     string viewState = ExtractViewState(response1); 
     string postData = String.Format(
       "__VIEWSTATE={0}&AdminCenterLoginControl$UserNameTextBox={1}&AdminCenterLoginControl$PasswordTextbox={2}&__EVENTTARGET=AdminCenterLoginControl_ActionButton", 
       viewState, USERNAME, PASSWORD); 

     // Set up the Request properties 
     webRequest = WebRequest.Create(LOGIN_URL) as HttpWebRequest; 
     webRequest.Method = "POST"; 
     webRequest.ContentType = "application/x-www-form-urlencoded"; 
     CookieContainer cookies = new CookieContainer(); 
     webRequest.CookieContainer = cookies; 

     // Post back to the form 
     using (StreamWriter requestWriter = new StreamWriter(webRequest.GetRequestStream())) 
     { 
      requestWriter.Write(postData); 
     } 

     // Read response 
     string response2 = new StreamReader(webRequest.GetResponse().GetResponseStream()).ReadToEnd(); 

     MessageBox.Show(response2); 
    } 

回答

0
>   // now we can send out cookie along with a request for the protected page 
>   webRequest = WebRequest.Create(TARGET_PAGE_URL) as 
>   HttpWebRequest; 
>   webRequest.CookieContainer = cookies; 
>   responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()); 

你不設置WebRequest.CookieContainer等於您先前生成的空白的cookie容器?

你不是應該做這樣的事情:

// we don't need the contents of the response, just the cookie it issues  
WebResponse response = webRequest.GetResponse(); 
cookies = response.cookies; 
response.Close(); 
+0

wllmsaccnt,首先WebResponse對象上沒有'cookies'集合,其次我認爲代碼是好的,因爲它表示兩個webRequest調用都指向'cookies'容器。第二個電話裏面收集了2個餅乾。 – issinoho 2010-10-27 18:20:37

2

這樣看來,MicrosoftOnline.com不使用Windows Live的ID(又名護照)進行登錄。這是一件令人遺憾的事情,因爲有可用的庫可以使登錄到LiveID非常簡單,適用於客戶端應用程序。

您的代碼先登錄登錄頁面,從響應中刪除cookie,然後嘗試導航到目標頁面。這與用戶行爲的正常流程不匹配。通常,用戶單擊鏈接以轉到目標頁面,如果用戶未登錄,則網站會將請求重定向到登錄頁面。登錄後,登錄頁面將重定向回原始請求的目標頁面。

您可以在瀏覽器中訪問admin.microsoftonline.com時查看登錄URL來查看此信息。您立即重定向到登錄頁面,但登錄頁面上的完整URL爲:https://admin.microsoftonline.com/login.aspx?ReturnUrl=%2fDefault.aspx

注意最後的ReturnUrl查詢參數。這會告訴登錄頁面登錄完成後重定向的頁面。

我不知道登錄頁面是否需要重定向,但由於這是實際最終用戶交互(可行)的主要路徑,而不是代碼所採用的路徑,因此需要考慮。除此之外,重定向到登錄/重定向回目標技術將自動爲目標域設置瀏覽器Cookie。

p.s.我還注意到Microsoft Online服務的電子郵件管理部分使用了不同的登錄URL。從此頁面(http://www.microsoft.com/online/signin.aspx)單擊Exchange託管服務管理中心鏈接會將您帶到http:admin.messaging.microsoft.com,它立即重定向到登錄URL https://sts.messaging.microsoft.com/login.aspx?ReturnUrl=%2fDefault.aspx%3fwa%3dwsignin1.0%26wtrealm%3dhttps%253a%252f%252fadmin.messaging.microsoft.com%26wctx%3drm%253d0%2526id%253dpassive%2526ru%253d%25252f%26wct%3d2010-10-27T17%253a11%253a50Z&wa=wsignin1.0&wtrealm=https%3a%2f%2fadmin.messaging.microsoft.com&wctx=rm%3d0%26id%3dpassive%26ru%3d%252f&wct=2010-10-27T17%3a11%3a50Z

域名STS .messaging.microsoft.com表明,微軟在線服務的Exchange託管服務部使用安全令牌服務,這表明這個登錄系統是在不同的能力之間的聯合單點登錄的服務。您可以使用類似Windows Identity Foundation (WIF)客戶端組件的方式連接到此服務器。它可以與其他Microsoft Online Services一起使用嗎?我不知道。

+0

謝謝你這麼全面的回答,dthorpe,你說的話很有道理。 如果你看看我在第一個問題中所做的修改,你會看到我已經剝離了該函數,以便它現在抓取viewstate,將登錄細節發佈到窗體然後讀取響應。 現在大概在這個階段我需要回應迴應,但我真的不確定究竟該做什麼。也許你可以建議下一步? 非常感謝。 – issinoho 2010-10-27 18:59:49