Qtwebkit 持久性 Cookie 不起作用

Posted

技术标签:

【中文标题】Qtwebkit 持久性 Cookie 不起作用【英文标题】:Qtwebkit persistence Cookie is not working 【发布时间】:2014-07-25 10:49:47 【问题描述】:

我正在尝试在基于 Qtwebkit 的浏览器中实现持久性以进行部分保存。我已经扩展了 QNetworkCookieJar。我没有覆盖任何文件,只是添加了一个保存和加载功能。这些函数被明确地调用。 我收到以下错误。代码取自 Qt5.1 示例中的浏览器代码。

QVariant::save: unable to save type 'QList<QNetworkCookie>' (type id: 1038).

我做错了什么吗..请帮助...附上我的 QNetworkCookie 实现如下

static const unsigned int JAR_VERSION = 23;
#if 1
QT_BEGIN_NAMESPACE

QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &list)

    stream << JAR_VERSION;
    stream << quint32(list.size());
    for (int i = 0; i < list.size(); ++i)
        stream << list.at(i).toRawForm();
    return stream;


QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)

    list.clear();

    quint32 version;
    stream >> version;

    if (version != JAR_VERSION)
        return stream;

    quint32 count;
    stream >> count;
    for(quint32 i = 0; i < count; ++i)
    
        QByteArray value;
        stream >> value;
        QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
        if (newCookies.count() == 0 && value.length() != 0) 
            qWarning() << "CookieJar: Unable to parse saved cookie:" << value;
        
        for (int j = 0; j < newCookies.count(); ++j)
            list.append(newCookies.at(j));
        if (stream.atEnd())
            break;
    
    return stream;

QT_END_NAMESPACE
#endif

CookieJar::CookieJar(QObject *parent)
    : QNetworkCookieJar(parent)

    load();


CookieJar::~CookieJar()

    save();


void CookieJar::load()

    QSettings cookieSettings("./cookies_dir/Browser/cookies.ini", QSettings::IniFormat);
    setAllCookies(qvariant_cast<QList<QNetworkCookie> >(cookieSettings.value(QLatin1String("cookies"))));

void CookieJar::save()

//    purgeOldCookies();
    QString directory = "./cookies_dir/Browser";
    if (!QFile::exists(directory)) 
        QDir dir;
        dir.mkpath(directory);
    
    QSettings cookieSettings(directory + QLatin1String("/cookies.ini"), QSettings::IniFormat);
    QList<QNetworkCookie> cookies = allCookies();
    qWarning("\n\n+=======================================================+\n\n");
    for (int i = cookies.count() - 1; i >= 0; --i) 
        qWarning()<< cookies.at(i).domain();
        qWarning()<< cookies.at(i).name();
        if (cookies.at(i).isSessionCookie())
            cookies.removeAt(i);
    
    qWarning("\n\n+=======================================================+\n\n");

    cookieSettings.setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(cookies));


void CookieJar::purgeOldCookies()

    QList<QNetworkCookie> cookies = allCookies();
    if (cookies.isEmpty())
        return;
    int oldCount = cookies.count();
    QDateTime now = QDateTime::currentDateTime();
    for (int i = cookies.count() - 1; i >= 0; --i) 
        if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now)
            cookies.removeAt(i);
    
    if (oldCount == cookies.count())
        return;
    setAllCookies(cookies);


bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)

    qWarning()<< url;
    return QNetworkCookieJar::setCookiesFromUrl(cookieList, url);

我已经使用下面的代码注册了 CookieJar。

   jar = new CookieJar(this);
    webView->page()->networkAccessManager()->setCookieJar(jar);

【问题讨论】:

【参考方案1】:

在保存或加载到 QSettings 之前,您必须调用 qRegisterMetaTypeStreamOperators&lt;QList&lt;QNetworkCookie&gt;&gt;("QList&lt;QNetworkCookie&gt;")

【讨论】:

【参考方案2】:

您需要使用qRegisterMetaTypeStreamOperators并定义流操作符。

这里是一个保存QList类型cookies的例子。在标题中声明流操作符:

class cookieJar: public QNetworkCookieJar

    bool save(const QUrl& url);
    bool load(const QUrl& url);

QDataStream &operator<<(QDataStream &out, const QNetworkCookie &cookie);
QDataStream &operator>>(QDataStream &in, QNetworkCookie &cookie);

在 cpp 文件中,您可以执行以下操作:

CookieJar::CookieJar(QObject* parent) :
    QNetworkCookieJar(parent)

    qRegisterMetaTypeStreamOperators<QNetworkCookie>("QNetworkCookie");


bool CookieJar::save(const QUrl &url)

    QList<QNetworkCookie> cookies = cookiesForUrl(url);
    QSettings cookieSettings;
    for(auto cookie : cookies)
    
        cookieSettings.setValue(cookie.name(), QVariant::fromValue(cookie));
    


bool CookieJar::load(const QUrl &url)

    QSettings cookieSettings;

    // empty list created here
    QList<QNetworkCookie> cookies;
    // retrieve all keys from cookies.ini
    QStringList keys = cookieSettings.allKeys();
    for(auto key: keys)
    
        QNetworkCookie cookie = qvariant_cast<QNetworkCookie>(cookieSettings.value(key, QVariant()));
        cookies.append(cookie);
    
    setCookiesFromUrl(cookies, url);
    return true;


QDataStream &operator<<(QDataStream &out, const QNetworkCookie &cookie)

    out << cookie.toRawForm();


QDataStream &operator>>(QDataStream &in, QNetworkCookie &cookie)

    QByteArray raw_data;
    in >> raw_data;
    QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(raw_data);
    cookie = cookies.at(0);

【讨论】:

以上是关于Qtwebkit 持久性 Cookie 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Spring安全令牌持久性存储不起作用

QtWebKit_cookie

React Native - Firebase 身份验证持久性不起作用

EJB3 的持久性不起作用

TommEE 会话持久存储不起作用

nginx add_header Set-Cookie 过期不起作用