我正在尝试编写一个实用程序,它将尝试登录到 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);
}
最佳答案
MicrosoftOnline.com 似乎不使用 Windows Live ID(又名 Passport)进行登录。这是一种耻辱,因为有可用的库使客户端应用程序登录 LiveID 变得非常简单。
您的代码首先访问登录页面,从响应中删除 cookie,然后尝试导航至目标页面。这与用户行为的正常流程不符。通常情况下,用户点击链接进入目标页面,如果用户未登录,网站将请求重定向到登录页面。登录后,登录页面重定向回最初请求的目标页面。
当您在浏览器中访问 admin.microsoftonline.com 时,您可以通过查看登录 URL 来了解这一点。您会立即被重定向到登录页面,但登录页面上的完整 URL 是:https://admin.microsoftonline.com/login.aspx?ReturnUrl=%2fDefault.aspx
注意末尾的 ReturnUrl 查询参数。这告诉登录页面在登录完成后重定向回哪个页面。
我不知道登录页面是否需要重定向,但由于这是实际最终用户交互(有效)的主要路径,而不是您的代码所采用的路径,因此需要考虑这一点。除其他外,重定向到登录/重定向回目标技术将负责自动为目标域设置浏览器 cookie。
附注我还注意到 Microsoft 在线服务的电子邮件管理部分使用不同的登录 URL。从此页面 (http://www.microsoft.com/online/signin.aspx) 单击 Exchange Hosted Services Administrative Center 链接会将您带到 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 表明 Microsoft Online Services 的 Exchange 托管服务部分正在使用安全 token 服务,这表明该登录系统能够进行联合单点登录在不同的服务之间。您可以使用类似 Windows Identity Foundation (WIF) 的方式连接到此客户端组件。这会与 Microsoft 在线服务的其余部分一起使用吗?我不知道。
关于c# - 使用 C# 以编程方式登录 Microsoft Online 网站,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4035638/