在Qt应用程序中共享cookie的最佳方式

时间:2015-11-01 19:19:21

标签: c++ qt cookies qnetworkaccessmanager

我可以使用QNetworkCookieJar来检索,存储和重新发送QNetworkManager的Cookie。多个QNetworkAccessManager个实例可以共享一个QNetworkCookieJar

到目前为止,我已经使用了多个QNetworkAccessManager个实例,每个类一个(我需要阅读的地方):

  1. 所以我可以在1..n QNetworkCookieJar个实例中共享一个单QNetworkAccessManager
  2. 或者最好只有一个单独的QNetworkAccessManager,其中一个Jar在所有QNetworkRequest中共享。 QNetworkAccessManager作为单个对象的方式是什么?文档说应该只有一个实例。那么我最好使用单身QNetworkAccessManager吗?
  3. 最合适的方式是什么?

    ------编辑-------

    kkoehne's answer从我能说的是正确的。这也是文档所说的。但是,在尝试这种方法时,我注意到了两个问题:

    1. 虽然我们现在每个网络服务有一个QNetworkAccessManager,但更改为一个单一实例意味着我需要始终区分我刚刚收到的"已完成" slot(从QNetworkAccessManager::finished调用的那个)。这是可行的,但不方便。
    2. 我们以不同的方式管理我们的读者 - 遗憾的是我忘了在问题中提到这一点。这使得几乎不可能使用QNetworkAccessManager的单个实例,因为成员函数是reentrant,但不是线程安全的。 (QNetworkAccessManager from ThreadPool
    3. 相关:QNetworkAccessManager get/post from different thread possible?

2 个答案:

答案 0 :(得分:1)

我认为您指的是QNetworkAccessManager,而不是QNetworkManager

您应该更喜欢在您的应用中使用一个QNetworkAccessManager。这不仅消除了同步QNetworkCookieJar的任何需要,而且还确保最佳地利用网络,并且共享缓存的内容等。

正如您自己注意到的那样,这也在QtNetworkAccessManager documentation中暗示:

  

对于整个Qt,一个QNetworkAccessManager应该足够了   应用

答案 1 :(得分:1)

这是我所做的(并且似乎有效):

  1. 我们在线程中读到时,我无法使用单个QNetworkAccessManager
  2. 分享QNetworkCookieJar不是一个选项,因为它不是线程安全
  3. 但是创建我自己的小线程安全 - 派生自QNetworkCookieJar - 类很容易。我只需要担心5个虚函数。我可以在QNetworkAccessManager之间分享这个线程安全的cookie罐。

    我在这里遇到了一定的风险,因为QObject的其他公共成员函数不是线程安全的并且可能会崩溃,但这些似乎并没有在那个用例中使用。

    请求的示例代码:

    /*!
     * Cookie manager, which allows thread safe sharing of cookies
     */
    class BLACKCORE_EXPORT CCookieManager : public QNetworkCookieJar
    {
        Q_OBJECT
    
    public:
        //! Constructor, only allowed from BlackCore::CApplication
        CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent = nullptr);
    
        //! \copydoc QNetworkCookieJar::setCookiesFromUrl
        //! \threadsafe
        virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url) override;
    
        //! \copydoc QNetworkCookieJar::cookiesForUrl
        //! \threadsafe
        virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override;
    
        //! Cookies for request
        //! \threadsafe
        QList<QNetworkCookie> cookiesForRequest(const QNetworkRequest &request) const;
    
        //! \copydoc QNetworkCookieJar::deleteCookie
        //! \threadsafe
        virtual bool deleteCookie(const QNetworkCookie &cookie) override;
    
        //! Delete all cookies
        //! \threadsafe
        void deleteAllCookies();
    
        //! \copydoc QNetworkCookieJar::insertCookie
        //! \threadsafe
        virtual bool insertCookie(const QNetworkCookie &cookie) override;
    
        //! \copydoc QNetworkCookieJar::updateCookie
        //! \threadsafe
        virtual bool updateCookie(const QNetworkCookie &cookie) override;
    
    private:
        mutable QReadWriteLock m_lock { QReadWriteLock::Recursive };
    };
    
    CCookieManager::CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent) : QNetworkCookieJar(parent)
    {
        // code
    }
    
    bool CCookieManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url)
    {
        QWriteLocker l(&m_lock);
        return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
    }
    
    QList<QNetworkCookie> CCookieManager::cookiesForUrl(const QUrl &url) const
    {
        QReadLocker l(&m_lock);
        const QList<QNetworkCookie> cookies(QNetworkCookieJar::cookiesForUrl(url));
        return cookies;
    }
    
    QList<QNetworkCookie> CCookieManager::cookiesForRequest(const QNetworkRequest &request) const
    {
        return cookiesForUrl(request.url());
    }
    
    bool CCookieManager::deleteCookie(const QNetworkCookie &cookie)
    {
        QWriteLocker l(&m_lock);
        return QNetworkCookieJar::deleteCookie(cookie);
    }
    
    bool CCookieManager::insertCookie(const QNetworkCookie &cookie)
    {
        QWriteLocker l(&m_lock);
        return QNetworkCookieJar::insertCookie(cookie);
    }
    
    bool CCookieManager::updateCookie(const QNetworkCookie &cookie)
    {
        QWriteLocker l(&m_lock);
        return QNetworkCookieJar::updateCookie(cookie);
    }
    
    void CCookieManager::deleteAllCookies()
    {
        QWriteLocker l(&m_lock);
        this->setAllCookies(QList<QNetworkCookie>());
    }