- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了一些 C++ 代码(使用 libcurl)来登录 WordPress 博客。不过我遇到了一个有趣的问题。成功登录后,Libcurl 不会发送适当的 cookie。首先,我获取登录页面(解析发布数据并获取 WP 所需的 cookie)。这完成了它应该做的事情,你会看到 libcurl 已经适本地“添加了 cookie wordpress_test_cookie”。接下来我发布登录数据。 WordPress登录实现登录成功后的重定向。从 302 响应和 header 中的 Location 字段可以看到。我还获得了 cookie,以便我现在可以导航到 wp-admin 面板。接下来,我获取重定向位置并尝试获取它。这就是它失败的地方。
编译使用:
g++-5 -o loginTest loginTest.cpp -lcurl -std=c++17
G++ 版本:
g++ (Ubuntu 5.1.0-0ubuntu11~14.04.1) 5.1.0
curl 版本:
curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3
完整代码:
#include <curl/curl.h>
#include <iostream>
#include <regex>
#include <string>
#include <vector>
using namespace std;
string ParseLoginPageForPOSTParameters(string loginPageBody);
size_t MyWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
int main() {
CURL *curl;
if (curl_global_init(CURL_GLOBAL_NOTHING) != 0) {
cerr << "Something catastrophic happened during global init" << endl;
return 1;
}
curl = curl_easy_init();
if (curl) {
//First get the login page (to parse post data and get a cookie that WP requires)
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/wp-login.php");
//Empty string for encoding means accept all that are supported
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, 0);
string loginPageBody = "";
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &loginPageBody);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &MyWriteCallback);
curl_easy_perform(curl);
//We now have the login page stored in loginPageBody
string parsedPostParameters = ParseLoginPageForPOSTParameters(loginPageBody);
string completePostParameters = "log=<myUsername>&pwd=<myPassword>" + parsedPostParameters;
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, completePostParameters.c_str());
curl_easy_perform(curl);
//We now sent the login info
char *newUrl;
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &newUrl);
cout << flush;
cout << "Redirecting to " << newUrl << endl;
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(curl, CURLOPT_URL, newUrl);
string afterLoginBody = "";
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &afterLoginBody);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &MyWriteCallback);
curl_easy_perform(curl);
cout << flush;
cout << afterLoginBody;
} else {
cerr << "Couldnt easy_init" << endl;
}
curl_easy_cleanup(curl);
return 0;
}
string ParseLoginPageForPOSTParameters(string loginPageBody) {
string postParameters = "";
//find all input tags, they're formatted like this
// <input type="hidden" name="testcookie" value="1" />
regex inputRegex(R"V.S.(<input.*?/>)V.S.", regex::icase|regex::optimize);
auto firstInputMatch = sregex_iterator(loginPageBody.begin(), loginPageBody.end(), inputRegex);
auto lastInputMatch = sregex_iterator();
for (sregex_iterator i = firstInputMatch; i != lastInputMatch; ++i) {
//for each input field in the form
smatch inputMatch = *i;
string inputMatchString = inputMatch.str();
regex nameRegex(R"V.S.(name="(.*?)")V.S.", regex::icase|regex::optimize);
regex valueRegex(R"V.S.(value="(.*?)")V.S.", regex::icase|regex::optimize);
smatch nameMatch, valueMatch;
if (regex_search(inputMatchString,nameMatch,nameRegex) && regex_search(inputMatchString,valueMatch,valueRegex)) {
//Found a name and value pair inside the input field
string value = valueMatch[1].str();
string name = nameMatch[1].str();
if (name != "log" && name != "pwd" && name != "" && value != "") {
postParameters += "&"+name+"="+value;
}
}
}
return postParameters;
}
size_t MyWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata) {
//userdata is a std::string
size_t dataAmnt = size * nmemb;
string *userdataString = (string*)userdata;
for (int i=0; i<nmemb; ++i) {
*userdataString += ptr[i];
}
return size * nmemb;
}
完整输出:
* Hostname was NOT found in DNS cache
* Trying <IP of example.com>...
* Connected to example.com (<IP of example.com>) port 80 (#0)
> GET /wp-login.php HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0
Host: example.com
Accept: */*
Accept-Encoding: deflate, gzip
< HTTP/1.1 200 OK
< Date: Sat, 17 Oct 2015 15:56:43 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 4759
< Connection: keep-alive
< Keep-Alive: timeout=30
* Server Apache/2 is not blacklisted
< Server: Apache/2
< X-Powered-By: PHP/5.3.29
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-cache, must-revalidate, max-age=0
< Pragma: no-cache
* Added cookie wordpress_test_cookie="WP+Cookie+check" for domain example.com, path /, expire 0
< Set-Cookie: wordpress_test_cookie=WP+Cookie+check; path=/
< X-Frame-Options: SAMEORIGIN
<
* Connection #0 to host example.com left intact
* Found bundle for host example.com: 0x9a0c10
* Re-using existing connection! (#0) with host example.com
* Connected to example.com (<IP of example.com>) port 80 (#0)
> POST /wp-login.php HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0
Host: example.com
Accept: */*
Accept-Encoding: deflate, gzip
Cookie: wordpress_test_cookie=WP+Cookie+check
Content-Length: 115
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 115 out of 115 bytes
< HTTP/1.1 302 Found
< Date: Sat, 17 Oct 2015 15:56:44 GMT
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 215
< Connection: keep-alive
< Keep-Alive: timeout=30
* Server Apache/2 is not blacklisted
< Server: Apache/2
< X-Powered-By: PHP/5.3.29
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-cache, must-revalidate, max-age=0
< Pragma: no-cache
* Replaced cookie wordpress_test_cookie="WP+Cookie+check" for domain example.com, path /, expire 0
< Set-Cookie: wordpress_test_cookie=WP+Cookie+check; path=/
< X-Frame-Options: SAMEORIGIN
* Added cookie wordpress_0c9410477a030adc6c64b9a4a70917f3="admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7C2bd7e640536c134e3426ef89f1a62b44bd011a4d93d5ffa88f336167d1144fb2" for domain example.com, path /wp-content/plugins, expire 1446350204
< Set-Cookie: wordpress_0c9410477a030adc6c64b9a4a70917f3=admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7C2bd7e640536c134e3426ef89f1a62b44bd011a4d93d5ffa88f336167d1144fb2; expires=Sun, 01-Nov-2015 03:56:44 GMT; path=/wp-content/plugins; httponly
* Added cookie wordpress_0c9410477a030adc6c64b9a4a70917f3="admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7C2bd7e640536c134e3426ef89f1a62b44bd011a4d93d5ffa88f336167d1144fb2" for domain example.com, path /wp-admin, expire 1446350204
< Set-Cookie: wordpress_0c9410477a030adc6c64b9a4a70917f3=admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7C2bd7e640536c134e3426ef89f1a62b44bd011a4d93d5ffa88f336167d1144fb2; expires=Sun, 01-Nov-2015 03:56:44 GMT; path=/wp-admin; httponly
* Added cookie wordpress_logged_in_0c9410477a030adc6c64b9a4a70917f3="admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7Ca5b38cc8bb0d656573d147fcfc00e54016271723bee9bf3613c5c45f504b2aca" for domain example.com, path /, expire 1446351204
< Set-Cookie: wordpress_logged_in_0c9410477a030adc6c64b9a4a70917f3=admin%7C1446307004%7CF38piRdUOaqnMHaJnETwYyMAdIU5Wsjq4quj9bDloZr%7Ca5b38cc8bb0d656573d147fcfc00e54016271723bee9bf3613c5c45f514b2aca; expires=Sun, 01-Nov-2015 03:56:44 GMT; path=/; httponly
< Location: http://www.example.com/wp-admin/
<
* Connection #0 to host example.com left intact
Redirecting to http://www.example.com/wp-admin/
* Hostname was NOT found in DNS cache
* Trying <IP of example.com>...
* Connected to www.example.com (<IP of example.com>) port 80 (#1)
> GET /wp-admin/ HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0
Host: www.example.com
Accept: */*
Accept-Encoding: deflate, gzip
< HTTP/1.1 302 Found
< Date: Sat, 17 Oct 2015 15:56:45 GMT
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 285
< Connection: keep-alive
< Keep-Alive: timeout=30
* Server Apache/2 is not blacklisted
< Server: Apache/2
< X-Powered-By: PHP/5.3.29
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-cache, must-revalidate, max-age=0
< Pragma: no-cache
< Location: http://www.example.com/wp-login.php?redirect_to=http%3A%2F%2Fwww.example.com%2Fwp-admin%2F&reauth=1
< Accept-Ranges: bytes
< Age: 0
<
* Connection #1 to host www.example.com left intact
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://www.example.com/wp-login.php?redirect_to=http%3A%2F%2Fwww.example.com%2Fwp-admin%2F&reauth=1">here</a>.</p>
</body></html>
如您所见,libcurl 正在发送不带任何 cookie 的 GET。因此,WordPress 将我重定向回登录页面,要求重新授权。另外,在发送 GET 请求时,它并没有像我发布时那样说“* Found Bundle for host example.com:...”,这似乎很奇怪。
有什么想法为什么会发生这种情况吗?
最佳答案
答案有点奇怪,但我认为是有效的。
我对网页的初始请求是“http://example.com ”地址。
但是重定向到“http://www.example.com ”地址。
由于“www”,libcurl 将新地址视为全新地址。
我认为这在技术上是有效的行为。
关于c - Libcurl 不会在重定向时发送 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33182925/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!