Frage

Ich muss eine Aktion im WordPress -Administrator -Panel programmatisch ausführen, kann aber nicht verwalten, wie man sich mit C# und httpwebRequest bei WordPress anmelde.

Hier ist was ich tue:

private void button1_Click(object sender, EventArgs e)
        {
            string url = "http://localhost/wordpress/wp-login.php";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            CookieContainer cookies = new CookieContainer();

            SetupRequest(url, request, cookies);
            //request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            //request.Headers["Accept-Language"] = "uk,ru;q=0.8,en-us;q=0.5,en;q=0.3";
            //request.Headers["Accept-Encoding"] = "gzip,deflate";
            //request.Headers["Accept-Charset"] = "windows-1251,utf-8;q=0.7,*;q=0.7";


            string user = "test";
            string pwd = "test";

            request.Credentials = new NetworkCredential(user, pwd);

            string data = string.Format(
                "log={0}&pwd={1}&wp-submit={2}&testcookie=1&redirect_to={3}",
                user, pwd, 
                System.Web.HttpUtility.UrlEncode("Log In"),
                System.Web.HttpUtility.UrlEncode("http://localhost/wordpress/wp-admin/"));

            SetRequestData(request, data);

            ShowResponse(request);
}

private static void SetupRequest(string url, HttpWebRequest request, CookieContainer cookies)
        {
            request.CookieContainer = cookies;
            request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; uk; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)";
            request.KeepAlive = true;
            request.Timeout = 120000;
            request.Method = "POST";
            request.Referer = url;
            request.ContentType = "application/x-www-form-urlencoded";
        }

        private void ShowResponse(HttpWebRequest request)
        {
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            responseTextBox.Text = (((HttpWebResponse)response).StatusDescription);
            responseTextBox.Text += "\r\n";
            StreamReader reader = new StreamReader(response.GetResponseStream());
            responseTextBox.Text += reader.ReadToEnd();
        }

        private static void SetRequestData(HttpWebRequest request, string data)
        {
            byte[] streamData = Encoding.ASCII.GetBytes(data);
            request.ContentLength = streamData.Length;

            Stream dataStream = request.GetRequestStream();
            dataStream.Write(streamData, 0, streamData.Length);
            dataStream.Close();
        }

Aber leider erhalte ich in Responce nur HTML -Quellcode der Anmeldeseite und es scheint, dass Cookies keine Sitzungs -ID enthalten. Alle Anfragen, die ich nach diesem Code ausführte, geben auch die HTML -Quelle der Anmeldeseite zurück, damit ich davon ausgehen kann, dass sie sich nicht richtig anmelden.

Kann mir jemand helfen, dieses Problem zu lösen oder ein Arbeitsbeispiel zu geben?


Die Hauptsache, die ich erreichen möchte, ist das Scannen nach neuen Bildern im NextGen Gallery -Plugin für WordPress. Gibt es eine XML-RPC-Möglichkeit, dies zu tun?

Danke im Voraus.

War es hilfreich?

Lösung 3

Danke an alle. Ich habe es geschafft, wie man es nur bei der Verwendung von Sockets funktioniert. WordPress sendet mehrere Set-Cookie Header aber HttpWebRequest Griff nur eine Instanz solcher Header, sodass einige Kekse verloren gehen. Bei Verwendung von Steckdosen kann ich alle benötigten Cookies erhalten und sich beim Admin -Panel anmelden.

Andere Tipps

Da WordPress eine Umleitung implementiert, verhindert, dass das WebRequest die Seite (Umleitung), das richtige Cookie zu erhalten.

Um den relevanten Keks zu erhalten, muss man Weiterleitungen verhindern.

request.AllowAutoRedirect = false;

Verwenden Sie den Cookie-Conatainer zum Login.

Siehe den folgenden Code: (basierend auf einem Beispiel aus Albaharis C# Buch)

        string loginUri = "http://www.someaddress.com/wp-login.php";
        string username = "username";
        string password = "pass";
        string reqString = "log=" + username + "&pwd=" + password;
        byte[] requestData = Encoding.UTF8.GetBytes(reqString);

        CookieContainer cc = new CookieContainer();
        var request = (HttpWebRequest)WebRequest.Create(loginUri);
        request.Proxy = null;
        request.AllowAutoRedirect = false;
        request.CookieContainer = cc;
        request.Method = "post";

        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = requestData.Length;
        using (Stream s = request.GetRequestStream())
            s.Write(requestData, 0, requestData.Length);

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            foreach (Cookie c in response.Cookies)
                Console.WriteLine(c.Name + " = " + c.Value);
        }

        string newloginUri = "http://www.someaddress.com/private/";
        HttpWebRequest newrequest = (HttpWebRequest)WebRequest.Create(newloginUri);
        newrequest.Proxy = null;
        newrequest.CookieContainer = cc;
        using (HttpWebResponse newresponse = (HttpWebResponse)newrequest.GetResponse())
        using (Stream resSteam = newresponse.GetResponseStream())
        using (StreamReader sr = new StreamReader(resSteam))
            File.WriteAllText("private.html", sr.ReadToEnd());
        System.Diagnostics.Process.Start("private.html");

Ich weiß nicht, ob andere dies hilfreich finden, aber ich habe nur die WordPress -API verwendet, um mich anzumelden. Ich habe einen Benutzer (CRON_USR) erstellt, der sich nachts als Teil eines Cron -Jobs "anmeldet" und einige Aufgaben erledigt. Der Code lautet:

require(dirname(__FILE__) . '/wp-load.php' );
$user = wp_authenticate(CRON_USR, CRON_PWD);
wp_set_auth_cookie($user->ID, true, $secure_cookie); //$secure_cookie is an empty string
do_action('wp_login', CRON_USR);
wp_redirect('http://www.mysite.com/wp-admin/');
NameValueCollection loginData = new NameValueCollection();
loginData.Add("username", "your_username");
loginData.Add("password", "your_password");

WebClient client = new WebClient();
string source = Encoding.UTF8.GetString(client.UploadValues("http://www.site.com/login", loginData));

string cookie = client.ResponseHeaders["Set-Cookie"];

Ich sehe kein offensichtliches Problem mit Ihrem Code, sorry. WordPress verfügt jedoch über eine XML-RPC-Schnittstelle, die in der Admin-Schnittstelle aktiviert werden muss. Ich habe einige Python -Skripte für diese Oberfläche geschrieben und es hat wie ein Zauber funktioniert.

Ich habe dies mit meinem WordPress.com -Konto versucht (geschützt mit SSL). Ich stellte fest, dass am einfachsten .NET-Sockets am einfachsten sind, um die HTTP-Header "Set-Cookie" zu erhalten, dann die Header an .NET-Cookie-Objekte analysieren und dann mit den Cookies für HTTPWebRequest Cookontainer verwenden.

Der einfachste Weg, mit SSL über Sockets zu arbeiten, besteht darin, SSLStream über Netzwerkestream zu implementieren, die an den Sockel gebunden sind.

Beispiel:

private void LogIn()
    {
        string fulladdress = "hostname.wordpress.com";
        string username = HttpUtility.UrlEncode("username");
        string password = HttpUtility.UrlEncode("password");

        string formdata = "log={0}&pwd={1}&redirect_to=http%3A%2F%2F{2}%2Fwp-admin%2F&testcookie=1";
        formdata = string.Format(formdata, username, password, fulladdress);
        IPHostEntry entry = Dns.GetHostEntry(fulladdress);


        Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        s.Connect(entry.AddressList[0], 443);

        NetworkStream ns = new NetworkStream(s);

        System.Net.Security.SslStream ssl = new System.Net.Security.SslStream(ns);
        byte[] data = Encoding.UTF8.GetBytes(String.Format(WpfApplication2.Properties.Resources.LogRequest, "https://" + fulladdress, fulladdress, form.Length, username, password));

        ssl.AuthenticateAsClient(fulladdress);
        ssl.Write(data, 0, data.Length);

        StringBuilder sb = new StringBuilder();
        byte[] resp = new byte[128];
        int i = 0;
        while (ssl.Read(resp, 0, 128) > 0)
        {
            sb.Append(Encoding.UTF8.GetString(resp));
        }

        List<String> CookieHeaders = new List<string>();
        foreach (string header in sb.ToString().Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
        {
            if (header.StartsWith("Set-Cookie"))
            {
                CookieHeaders.Add(header.Replace("Set-Cookie: ", ""));
            }
        }

        CookieContainer jar = new CookieContainer();
        foreach (string cook in CookieHeaders)
        {
            string name, value, path, domain;
            name = value = path = domain = "";

            string[] split = cook.Split(';');
            foreach (string part in split)
            {
                if (part.StartsWith(" path="))
                {
                    path = part.Replace(" path=", "");
                }
                if (part.StartsWith(" domain="))
                {
                    domain = part.Replace(" domain=", "");
                }
                if (!part.StartsWith(" path=") && !part.StartsWith(" domain=") && part.Contains("="))
                {
                    name = part.Split('=')[0];
                    value = part.Split('=')[1];
                }
            }

            jar.Add(new Cookie(name, value, path, domain));
        }

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://" + fulladdress + "/wp-admin/index.php");
        req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3";
        req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        req.KeepAlive = false;
        req.AllowAutoRedirect = false;
        req.Referer = "https://" + fulladdress + "/wp-login.php";
        req.ContentType = "application/x-www-form-urlencoded";
        req.CookieContainer = jar;
        req.AllowAutoRedirect = true;
        req.AutomaticDecompression = DecompressionMethods.GZip;
        req.Method = "GET";
        req.Timeout = 30000;

        HttpWebResponse response = (HttpWebResponse)req.GetResponse();

        using (System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream(), Encoding.UTF8))
        {
            MessageBox.Show(sr.ReadToEnd());
        }
    }

Der Code ist nicht sehr effizient, zeigt jedoch den Prozess der Anmeldung in der Verwaltungsschnittstelle.

Ich hoffe es hilft :)

Tomerbu hat die beste Antwort für mich, aber etwas fehlte etwas.

In seinem Code, Remant:

 foreach (Cookie c in response.Cookies)
            Console.WriteLine(c.Name + " = " + c.Value);

durch

if (response.Cookies != null)
    {
        foreach (Cookie currentcook in response.Cookies)
             request.CookieContainer.Add(currentcook); //This is the key !!!
    }

Als nächstes müssen Sie CookieContainer wiederverwenden.

Tomerbus Antwort funktioniert für mich mit den folgenden Ergänzungen. Ich musste ein SSL -Zertifikat auf der Website installieren, Unterstützung für TLS1.2 hinzufügen und die Benutzeragent einstellen, damit dies funktioniert. Ohne TLS1.2 lehnte der Webserver meine Verbindungsanforderung sofort ab. Ohne das SSL -Zertifikat betrachtete die WordPress -Site nicht, dass mein C# Bot für nachfolgende WebRequests angemeldet wurde (obwohl der Anmeldung erfolgreich war).

*** Wichtiger Hinweis zu TLS: Ich bin ein Sicherheitsprotokoll -Anfänger und stelle nur das an, was für mich funktioniert hat. Ich habe das .NET 4.7.2 -Entwicklerpaket installiert und das Ziel -Framework für mein C# -Projekt in .NET 4.7.2 geändert. Ich musste jedoch immer noch den ServicePointManager.securityProtocol wie unten gezeigt ändern. Suche nach Best Practices, einschließlich Aktualisierung von .NET und Angabe mehrerer TLS -Versionen in einer Bitwise ORED -Anweisung.

// Add support for TLS 1.2 (note bitwise OR)
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;

...
request.Proxy = null;
request.AllowAutoRedirect = false;
request.CookieContainer = cc;
request.Method = "post";

// Add UserAgent
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top