- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一个使用 QWebEngineView 和 QNetworkAccessManager 的 Qt 云客户端应用程序。我遇到的问题描述如下:
该应用程序有一个自定义登录表单。根据用户凭据,我执行一系列手动请求(“post”和“get”)以获取相关 session cookie。
...
//get session cookie
QNetworkAccessManager accessManager;
connect(&accessManager, &QNetworkAccessManager::proxyAuthenticationRequired, [=] (const QNetworkProxy &proxy, QAuthenticator *authenticator){
//perform proxy auth in case a proxy is set
});
QNetworkReply * reply = Q_NULLPTR;
QNetworkRequest request(QUrl(/*url*/));
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
request.setRawHeader("Cache-Control", "no-cache");
QByteArray data(/*data for auth*/);
reply = accessManager.post(request,data); //ajax login
QEventLoop waitReplyHandler;
QObject::connect(reply, SIGNAL(finished()), &waitReplyHandler, SLOT(quit()));
//wait for reply from url
waitReplyHandler.exec();
QVariant sessionCookie = reply->header(QNetworkRequest::SetCookieHeader); //this cookie is used to retrieve second "session cookie"
...
//Different function - get user session cookie
QNetworkRequest request(QUrl(/*url*/));
request.setHeader(QNetworkRequest::CookieHeader, sessionCookie);
QNetworkReply * reply = accessManager.get(request);
QEventLoop waitReplyHandler;
QObject::connect(reply, SIGNAL(finished()), &waitReplyHandler, SLOT(quit()));
//wait for reply from url
waitReplyHandler.exec();
QString redirect = reply->header(QNetworkRequest::LocationHeader).toString();
QVariant userSessionCookie = reply->header(QNetworkRequest::SetCookieHeader);
在此之后,我为 QWebEngineView 设置了一个请求拦截器:
interceptor = new CWebEngineUrlRequestInterceptor(sessionCookie.value<QList<QNetworkCookie>>().first(),
userSessionCookie.value<QList<QNetworkCookie>>().first(),
this);
m_tabWebview->webEngineView()->page()->profile()->setRequestInterceptor(interceptor);
m_tabWebview->webEngineView()->load(redirectUrl); //Obtained from "redirect" string variable from second manual request
想法是在每次加载调用 Web 引擎 View 时使用这些手动获取的 cookie:
void CWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
QByteArray sessionCookie = QByteArray(m_sessionCookie.name() + "=" + m_sessionCookie.value());
QByteArray userSessionCookie = QByteArray(m_userSessionCookie.name() + "=" + m_userSessionCookie.value());
QByteArray requestCookies = sessionCookie + "; " + userSessionCookie;
info.setHttpHeader(QByteArray("Cookie"), requestCookies);
}
这项工作非常正常,在加载到 redirectUrl 之后,Web View 将显示云的主页,用户已经登录。但是,如果我将 QNetworkProxy 设置为应用程序:
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName(proxyUrl);
proxy.setPort(proxyPort.toInt());
QNetworkProxy::setApplicationProxy(proxy);
上面的序列将在 web View 中显示我的目标 url 的登录页面。我相信应用程序级代理设置应该与 QWebEngineView 无关。手动请求有效,我能够获取 cookie,也调用了 interceptRequest,但代理中继后不保留 cookie。我还尝试手动设置 header 以代理自身:
QByteArray requestCookies = m_cookies.first().name() + "=" + m_cookies.first().value() + "; " +
m_cookies.last().name() + "=" + m_cookies.last().value();
QNetworkProxy proxy(QNetworkProxy::applicationProxy());
proxy.setRawHeader(QByteArray("Cookie"), requestCookies);
QNetworkProxy::setApplicationProxy(proxy);
//...
//check headers are set to proxy
QByteArray cookieVar = QNetworkProxy::applicationProxy().rawHeader(QByteArray("Cookie"));
if(cookieVar.isEmpty()){
std::cout<<"empty cookies to proxy ";
}
else{
std::cout<<cookieVar.toStdString()<<std::endl;
}
日志没问题,我可以看到 cookie 已附加到代理。
如果没有互联网连接的时间超过 session cookie 的过期时间,则实现此自定义登录机制以处理自动登录。如何设置应用程序级代理以使用手动获取的 session cookie?
提前谢谢你。
最佳答案
这似乎是与代理身份验证机制相关的网络引擎框架中的错误。但是我找到了解决方法:当调用 QWebEnginePage::proxyAuthenticationRequired 时,在验证器对象的数据设置后,我只是再次调用加载到 requestUrl 参数。
connect(app->webview()->page(), &QWebEnginePage::proxyAuthenticationRequired, [=] (const QUrl &requestUrl, QAuthenticator *authenticator, const QString &proxyHost){
proxyAuthSequence(authenticator, proxyHost);
app->webview()->load(requestUrl);
});
想法是将初始加载视为虚拟加载,仅设置身份验证数据,然后再次加载 url。随后的加载调用将不再触发此信号。所以,基本上问题出在身份验证机制上。
该错误也已提交给 Qt: https://bugreports.qt.io/browse/QTBUG-58121
关于c++ - Qt 5.7 QNetworkProxy 没有考虑cookies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41505707/
我一直认为使用“if”比捕获异常要好得多(就性能而言)。例如,这样做: User u = Users.getUser("Michael Jordan"); if(u!=null) System.
我正在尝试使用下一个格式将字符转换为日期。我有下一个数据框 i (我在最后添加了 dput() 版本的数据框): Date 1 Dec_28_2012_9:
考虑到 PHP 中的日期戳,我如何计算持续时间?我在日期之间使用的日期格式是“Y-m-d H:i:s”, 我的工作代码只能计算时间之间的持续时间而不考虑日期。 下面是我的代码: $assigned_t
我正在尝试解释 GLMM 中的自相关。我的响应变量是 bool 值,它表示一组 hive 的生命周期中是否存在 en 事件。我试图用一组描述每个巢状态的数值变量来预测此类事件的概率。因此,我在广义模型
我对如何解释 undefined variable 感到有点困惑(我不确定你现在是否可以)。我正在尝试使用以下代码底部附近的 if else 语句(已注释掉的行)。 这个想法是,如果请求歌曲的人不是与
Bjarne Stroustrup 的 The C++ Programming Language Fourth Edition 中的以下内容是什么意思? "Consider . (dot) suspe
我想要一个主元素,边 block 漂浮在它的右侧。我不知道边 block 的数量,也不知道它们的最终总高度。但是我的主要元素应该具有相同的高度(请参阅以下示例以更好地理解),而无需使用列。 (虚线部分
我在每个 TextView 上都有以下警告(来自 Lint),在我的 XML 中有一个 ID。 Consider making the text value selectable by specify
目前,我有 6 条曲线,以 6 种不同的颜色显示,如下所示。 这 6 条曲线实际上是由 一个相同实验 的 6 次试验生成的。这意味着,理想情况下它们应该是相同的曲线,但由于噪声和不同的试验参与者,它们
winner of a recent Wikipedia vandalism detection competition建议可以通过“检测考虑到 QWERTY 的随机键盘点击来改进检测键盘布局”。 示
多年来,我一直在编写 C 语言,主要是在嵌入式环境中,并且对指针有一个非常好的心智模型——我不必明确地考虑如何使用它们,我对指针算法 100% 感到满意,指针数组,指针指针等。 我写的 C++ 很少,
我正在使用 Boost.Date_time 来获取两个日期之间的时差。我希望代码在这些天也考虑夏令时的变化,并给我正确的时间间隔。 考虑这个例子。 2015 年 11 月 1 日,美国的 DST 将发
我有一个(人类)名字的向量,全部用大写字母表示: names <- c("FRIEDRICH SCHILLER", "FRANK O'HARA", "HANS-CHRISTIAN ANDERSEN")
我想呈现一个表单小部件。这是我要生成的原始 HTML: 使用这个: {{ form_row(form.email, { 'type' : 'email', 'attr' : { 'class' :
我正在开发一个 python 项目,它使用 pythonnet 和几个 C# dll 作为依赖项。 由于我不想将 dll 推送到 git 存储库,因此我调整了 .gitignore 文件。但是,现在
考虑到上午/下午,我想将字符串转换为 php 数据时间。 我想将 '03/06/2015 12:17 am' 转换为 php datatime。 我试过了, $myDateTime = DateTim
我想排除那些具有相同标题和同一年份的实例。 title votes ranking year 0 Wonderland 19 7.9 1931 1
例如对于一个 EditText,通常指定 android:inputType="numberDecimal"用于文本字段应该包含十进制数。但这假设“。”用作小数点分隔符,在某些国家/地区使用“,”代替
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
作为练习,我决定学习 Java 中的 lambda 表达式。我想重写我发现笨拙且冗长的旧代码。它检查命令行参数是否是(1)文件路径或(2)目录路径。在(1)场景中,它将命令行参数传递给方法。在 (2)
我是一名优秀的程序员,十分优秀!