我有一个WebForms应用程序,它公开了一些WebAPI方法。该应用程序使用标准表单身份验我在正确认证后可以从浏览器调用方法。
现在我想使用HttpClient从c#应用程序调用API,但总是收到错误403“Forbidden”。
我可以看到cookies容器包含SessionId cookie。
代码:
var cookieContainer = new CookieContainer();
// authenticate
{
var webRequestHandler = new WebRequestHandler();
webRequestHandler.CookieContainer = cookieContainer;
webRequestHandler.UseCookies = true;
var client = new HttpClient(webRequestHandler);
client.BaseAddress = new Uri("https://localhost/<WEBFORMSAPP>/");
string unid = "<USERNAME$FIELD$NAME>";
string pwdid = "<PASSWORD$FIELD$NAME>";
HttpContent loginData = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(unid, "<USERNAME>"),
new KeyValuePair<string, string>(pwdid, "<PASSWORD>"),
}
);
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var postResult = client.PostAsync("<LOGINPAGE.aspx>", loginData);
postResult.Wait();
postResult.Result.EnsureSuccessStatusCode();
}
// call web api
{
var webRequestHandler = new WebRequestHandler();
webRequestHandler.CookieContainer = cookieContainer;
webRequestHandler.UseCookies = true;
var client = new HttpClient(webRequestHandler);
client.BaseAddress = new Uri("https://localhost/<WEBFORMSAPP>/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var r = client.GetAsync("api/<SOME_METHOD>");
r.Wait();
r.Result.EnsureSuccessStatusCode(); // Fails with 403 error
}
答案 0 :(得分:0)
要构建正确的Web请求,我们需要为服务器提供正确的__VIEWSTATE值以及导致回发的按钮名称(除了登录/密码对)。
首先,我们需要向登录页面发出GET请求,然后提取__VIEWSTATE值。
我使用了此博文中的代码: http://odetocode.com/articles/162.aspx
创建授权cookie的代码:
public CookieContainer CreateAuthorizationCookies(string login, string password)
{
var result = new CookieContainer();
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var webRequestHandler = new WebRequestHandler();
webRequestHandler.CookieContainer = result;
webRequestHandler.UseCookies = true;
var client = new HttpClient(webRequestHandler);
client.BaseAddress = new Uri("https://*********/");
// get viewstate
string viewstate;
{
var r = client.GetStringAsync("***/LoginPage.aspx");
r.Wait();
// see http://odetocode.com/articles/162.aspx
viewstate = ExtractViewState(r.Result);
}
HttpContent loginData = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("__VIEWSTATE", viewstate),
new KeyValuePair<string, string>("***$UserName", login),
new KeyValuePair<string, string>("***$Password", password),
new KeyValuePair<string, string>("***$LoginButton", "Log In"), // "value" of the HTML input element
}
);
var postResult = client.PostAsync("****/LoginPage.aspx", loginData);
postResult.Wait();
postResult.Result.EnsureSuccessStatusCode();
return result;
}
之后我们可以在进一步的请求中使用创建的CookieContainer。