我正在努力开发一个C#类来登录Web主机(Hostgator)上的cPanel。
在PHP中,使用Curl扩展非常容易,如下所示:
$url = "http://mysite.com:2082/";
$c = curl_init($url);
curl_setopt($c, CURLOPT_USERPWD, 'user:password');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($c);
if ($result === false)
$result = curl_error($c);
curl_close($c);
file_put_contents('log.txt', $result);
//print_r($result);
现在这是我的C#类,其中有各种尝试使其工作被注释掉:
class HTTPHandler
{
public static string Connect (string url, string userName, string password)
{
string result;
try
{
// An initial @ symbol in the password must be escaped
if (password.Length > 0)
if (password[0] == '@')
password = "\\" + password;
// Create a request for the URL.
WebRequest request = WebRequest.Create(url);
request.PreAuthenticate = true;
request.Credentials = new NetworkCredential(userName, password);
/*
var credCache = new CredentialCache();
credCache.Add(new Uri(url), "Basic",
new NetworkCredential(userName, password));
request.Credentials = credCache;
*/
//request.Method = "POST";
//request.ContentType = "application/x-www-form-urlencoded";
/*
// Create POST data and convert it to a byte array.
string postData = string.Format("user={0}&pass={1}", userName, password);
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
request.ContentType = "application/x-www-form-urlencoded";
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
*/
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Display the content.
result = string.Format("Server response:\n{0}\n{1}", response.StatusDescription, reader.ReadToEnd());
// Cleanup the streams and the response.
reader.Close();
dataStream.Close();
response.Close();
}
catch (Exception e)
{
result = string.Format("There was an error:\n{0}", e.Message);
}
return result;
}
}
}
但我在GetResponse阶段一直收到错误401(未经授权)。
当我在PHP和C#提交中比较本地主机测试页中的$ _SERVER变量时,除了发送端口之外,我得到的数据有点不同。关键的PHP_AUTH_USER和PHP_AUTH_PW是相同的。
我的操作系统是Windows 7 64位,我使用的是Visual C#2010。
我想解决方案非常简单,但到目前为止,我感到困惑。但是C#的相对新手。我希望有人可以提供帮助。
答案 0 :(得分:1)
您真的不需要设置PreAuthenticate
,只需让请求弄清楚。另外,我建议使用HttpWebRequest
代替WebRequest
。主要区别在于您可以设置CookieContainer
属性以启用Cookie。这有点令人困惑,因为默认情况下它会禁用cookie,您只需将其设置为new CookieContainer();
即可为您的请求启用Cookie。
这很重要,因为在身份验证期间发生了重定向,而auth cookie记录了您成功通过身份验证的事实。
也是一种编码风格注释:请确保在IDisposable
语句中包含所有using()
(例如响应,流和阅读器)。
另外我不清楚你为什么要在密码中转义@
。请求应自动处理所有编码需求。
完整的示例代码:
var request = WebRequest.CreateHttp(url);
request.Credentials = new NetworkCredential(username, password);
request.CookieContainer = new CookieContainer(); // needed to enable cookies
using (var response = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)))
return string.Format("Server response:\n{0}\n{1}", response.StatusDescription, reader.ReadToEnd());
编辑:抱歉所有的修改。我正在通过内存编写代码,并且正在努力使编码部分正确。
答案 1 :(得分:1)
这是使用System.Web,我必须设置项目属性以使用完整的.NET Framework 4来访问HttpUtility的此程序集,并在References中添加对System.Web的引用。
我没有测试所有重载的方法,但主要是cPanel连接,当userName存在时,身份验证凭据被添加到http标头。
另外,对于cPanel,我需要设置request.AllowAutoRedirect = false;所以我控制逐页访问,因为我没有设法捕获cookie。
以下是我提出的HTTP Helper类的代码:
class HTTPHandler
{
// Some default settings
const string UserAgent = "Bot"; // Change this to something more meaningful
const int TimeOut = 1000; // Time out in ms
// Basic connection
public static string Connect(string url)
{
return Connect(url, "", "", UserAgent, "", TimeOut);
}
// Connect with post data passed as a key : value pair dictionary
public static string Connect(string url, Dictionary<string, string> args)
{
return Connect(url, "", "", UserAgent, ToQueryString(args), TimeOut);
}
// Connect with a custom user agent specified
public static string Connect(string url, string userAgent)
{
return Connect(url, "", "", userAgent, "", TimeOut);
}
public static string Connect(string url, string userName, string password, string userAgent, string postData, int timeOut)
{
string result;
try
{
// Create a request for the URL.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
if (userAgent == null)
userAgent = UserAgent;
request.UserAgent = userAgent;
request.Timeout = timeOut;
if (userName.Length > 0)
{
string authInfo = userName + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
request.AllowAutoRedirect = false;
}
if (postData.Length > 0)
{
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// Create POST data and convert it to a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
}
// Get the response.
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
using (StreamReader reader = new StreamReader(dataStream))
{
result = string.Format("Server response:\n{0}\n{1}", response.StatusDescription, reader.ReadToEnd());
}
}
}
catch (Exception e)
{
result = string.Format("There was an error:\n{0}", e.Message);
}
return result;
}
public static string ToQueryString(Dictionary<string, string> args)
{
List<string> encodedData = new List<string>();
foreach (KeyValuePair<string, string> pair in args)
{
encodedData.Add(HttpUtility.UrlEncode(pair.Key) + "=" + HttpUtility.UrlEncode(pair.Value));
}
return String.Join("&", encodedData.ToArray());
}
}