无法使用C#WebRequest登录cPanel

时间:2011-10-22 15:10:54

标签: c# login cpanel

我正在努力开发一个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#的相对新手。我希望有人可以提供帮助。

2 个答案:

答案 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());
    }
}