Вход на веб-сайт Microsoft Online с помощью C # - PullRequest
2 голосов
/ 27 октября 2010

Я пытаюсь написать утилиту, которая попытается войти на веб-сайт Microsoft Online Admin и сообщить о ее доступности.

Используя код в основном из этой статьи, 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);
    }

Ответы [ 2 ]

2 голосов
/ 27 октября 2010

Может показаться, что MicrosoftOnline.com не использует идентификаторы Windows Live ID (или паспорт) для входа в систему. Это позор, поскольку есть доступные библиотеки, которые делают вход в LiveID довольно простым для клиентских приложений.

Ваш код сначала попадает на страницу входа, удаляет файлы cookie из ответа, а затем пытается перейти на целевую страницу. Это не соответствует нормальному поведению пользователя. Обычно пользователь нажимает на ссылку, чтобы перейти на целевую страницу, и веб-сайт перенаправляет запрос на страницу входа в систему, если пользователь не вошел в систему. После входа в систему страница входа перенаправляется обратно на первоначально запрошенную целевую страницу.

Вы можете увидеть это, посмотрев URL-адрес для входа при посещении admin.microsoftonline.com в браузере. Вы сразу же перенаправлены на страницу входа, но полный 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 в онлайн-службах Microsoft использует службу маркеров безопасности, что говорит о том, что эта система входа в систему поддерживает федеративный единый вход. между разными сервисами. Вы можете подключиться к этому, используя что-то вроде клиентских компонентов Windows Identity Foundation (WIF) . Будет ли это работать с остальными Microsoft Online Services? Я не знаю.

0 голосов
/ 27 октября 2010
>         // 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();
...