我正在尝试创建/修改dotclear博客。
对于大多数选项,我使用XmlRpc API(DotClear.MetaWeblog)。但我没有找到办法处理类别。
所以我开始查看Http数据包并尝试“与浏览器相同”。
这是我用来“Http POST”的方法
protected HttpStatusCode HttpPost(Uri url_, string data_, bool allowAutoRedirect_)
{
HttpWebRequest Request;
HttpWebResponse Response = null;
Stream ResponseStream = null;
Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(url_);
Request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)";
Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
Request.AllowAutoRedirect = allowAutoRedirect_;
// Add the network credentials to the request.
Request.Credentials = new NetworkCredential(Username, Password);
string authInfo = Username + ":" + Password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
Request.Headers["Authorization"] = "Basic " + authInfo;
Request.Method = "POST";
Request.CookieContainer = Cookies;
if(ConnectionCookie!=null)
Request.CookieContainer.Add(url_, ConnectionCookie);
if (dcAdminCookie != null)
Request.CookieContainer.Add(url_, dcAdminCookie);
Request.PreAuthenticate = true;
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = data_;
byte[] data = encoding.GetBytes(postData); //Encoding.UTF8.GetBytes(data_); //encoding.GetBytes(postData);
Request.ContentLength = data.Length;
Request.ContentType = "application/x-www-form-urlencoded";
Stream newStream = Request.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
try
{
// get the response from the server.
Response = (HttpWebResponse)Request.GetResponse();
if (!allowAutoRedirect_)
{
foreach (Cookie c in Response.Cookies)
{
if (c.Name == "dcxd")
ConnectionCookie = c;
if (c.Name == "dc_admin")
dcAdminCookie = c;
}
Cookies.Add(Response.Cookies);
}
// Get the response stream.
ResponseStream = Response.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader(ResponseStream, Encoding.UTF8);
string result = readStream.ReadToEnd();
if (Request.RequestUri == Response.ResponseUri)
{
_log.InfoFormat("{0} ==> {1}({2})", Request.RequestUri, Response.StatusCode, Response.StatusDescription);
}
else
{
_log.WarnFormat("RequestUri:{0}\r\nResponseUri:{1}\r\nstatus code:{2} Status descr:{3}", Request.RequestUri, Response.ResponseUri, Response.StatusCode, Response.StatusDescription);
}
}
catch (WebException wex)
{
Response = wex.Response as HttpWebResponse;
if (Response != null)
{
_log.ErrorFormat("{0} ==> {1}({2})", Request.RequestUri, Response.StatusCode, Response.StatusDescription);
}
Request.Abort();
}
finally
{
if (Response != null)
{
// Releases the resources of the response.
Response.Close();
}
}
if(Response !=null)
return Response.StatusCode;
return HttpStatusCode.Ambiguous;
}
所以要做的第一件事就是以管理员身份进行身份验证。这是代码:
protected bool HttpAuthenticate()
{
Uri u = new Uri(this.Url);
Uri url = new Uri(string.Format("{0}/admin/auth.php", u.GetLeftPart(UriPartial.Authority)));
string data = string.Format("user_id={0}&user_pwd={1}&user_remember=1", Username, Password);
var ret = HttpPost(url,data,false);
return (ret == HttpStatusCode.OK || ret==HttpStatusCode.Found);
}
现在我已通过身份验证,我需要获取xd_chek
信息(我可以在页面上找到,所以基本上它是/admin/category.php
+正则表达式{{1}上的GET }))
因此我已通过身份验证并拥有dotclear[.]nonce = '(.*)'
信息。最后要做的事情似乎是发布下一个类别。但当然它根本不起作用......这是代码:
xd_check
我哪里错了?
答案 0 :(得分:1)
最终我找到了解决方案。
似乎在认证和使用页面之间丢失了cookie。
所以我决定不使用框架的de CookiesContainer,而只是将cookie保存在字符串中并在每次请求时传递它们。
它很棒!
代码示例:
private string _cookieAsString = string.Empty;
protected string CookieAsString
{
get { return _cookieAsString; }
set
{
if (value != null)
{
if (!_cookieAsString.Contains(value))
{
if (_cookieAsString.Length == 0)
_cookieAsString = value;
else
_cookieAsString += string.Format(";{0}", value);
}
}
}
}
在HttpWebRequest中,我这样设置:
...
Request.Headers.Add(HttpRequestHeader.Cookie, CookieAsString);
...
将cookie保存在httpWebRequest中,如下所示:
...
CookieAsString = Response.Headers[HttpResponseHeader.SetCookie];
...