Add SameSite API to QNetworkCookie
Change-Id: I3f8b25418154f74bb55fa978b03465f75771d015 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
c0a17ecfaf
commit
37bd7b5733
@ -222,6 +222,29 @@ void QNetworkCookie::setSecure(bool enable)
|
||||
d->secure = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the "SameSite" option if specified in the cookie
|
||||
string, \c SameSite::Default if not present.
|
||||
|
||||
\since 6.1
|
||||
\sa setSameSite()
|
||||
*/
|
||||
QNetworkCookie::SameSite QNetworkCookie::sameSite() const
|
||||
{
|
||||
return d->sameSite;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the "SameSite" option of this cookie to \a sameSite.
|
||||
|
||||
\since 6.1
|
||||
\sa sameSite()
|
||||
*/
|
||||
void QNetworkCookie::setSameSite(QNetworkCookie::SameSite sameSite)
|
||||
{
|
||||
d->sameSite = sameSite;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.5
|
||||
|
||||
@ -435,6 +458,49 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
|
||||
\sa toRawForm(), parseCookies()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QNetworkCookie::SameSite
|
||||
\since 6.1
|
||||
|
||||
\value Default SameSite is not set. Can be interpreted as None or Lax by the browser.
|
||||
\value None Cookies can be sent in all contexts. This used to be default, but
|
||||
recent browsers made Lax default, and will now require the cookie to be both secure and to set SameSite=None.
|
||||
\value Lax Cookies are sent on first party requests and GET requests initiated by third party website.
|
||||
This is the default in modern browsers (since mid 2020).
|
||||
\value Strict Cookies will only be sent in a first-party context.
|
||||
|
||||
\sa setSameSite(), sameSite()
|
||||
*/
|
||||
|
||||
namespace {
|
||||
QByteArray sameSiteToRawString(QNetworkCookie::SameSite samesite)
|
||||
{
|
||||
switch (samesite) {
|
||||
case QNetworkCookie::SameSite::None:
|
||||
return QByteArrayLiteral("None");
|
||||
case QNetworkCookie::SameSite::Lax:
|
||||
return QByteArrayLiteral("Lax");
|
||||
case QNetworkCookie::SameSite::Strict:
|
||||
return QByteArrayLiteral("Strict");
|
||||
case QNetworkCookie::SameSite::Default:
|
||||
break;
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QNetworkCookie::SameSite sameSiteFromRawString(QByteArray str)
|
||||
{
|
||||
str = str.toLower();
|
||||
if (str == QByteArrayLiteral("none"))
|
||||
return QNetworkCookie::SameSite::None;
|
||||
if (str == QByteArrayLiteral("lax"))
|
||||
return QNetworkCookie::SameSite::Lax;
|
||||
if (str == QByteArrayLiteral("strict"))
|
||||
return QNetworkCookie::SameSite::Strict;
|
||||
return QNetworkCookie::SameSite::Default;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/*!
|
||||
Returns the raw form of this QNetworkCookie. The QByteArray
|
||||
returned by this function is suitable for an HTTP header, either
|
||||
@ -460,9 +526,9 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
|
||||
result += "; secure";
|
||||
if (isHttpOnly())
|
||||
result += "; HttpOnly";
|
||||
if (!d->sameSite.isEmpty()) {
|
||||
if (d->sameSite != SameSite::Default) {
|
||||
result += "; SameSite=";
|
||||
result += d->sameSite;
|
||||
result += sameSiteToRawString(d->sameSite);
|
||||
}
|
||||
if (!isSessionCookie()) {
|
||||
result += "; expires=";
|
||||
@ -999,7 +1065,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
|
||||
} else if (field.first == "httponly") {
|
||||
cookie.setHttpOnly(true);
|
||||
} else if (field.first == "samesite") {
|
||||
cookie.d->sameSite = field.second;
|
||||
cookie.setSameSite(sameSiteFromRawString(field.second));
|
||||
} else {
|
||||
// ignore unknown fields in the cookie (RFC6265 section 5.2, rule 6)
|
||||
}
|
||||
|
@ -57,11 +57,19 @@ class QUrl;
|
||||
class QNetworkCookiePrivate;
|
||||
class Q_NETWORK_EXPORT QNetworkCookie
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum RawForm {
|
||||
NameAndValueOnly,
|
||||
Full
|
||||
};
|
||||
enum class SameSite {
|
||||
Default,
|
||||
None,
|
||||
Lax,
|
||||
Strict
|
||||
};
|
||||
Q_ENUM(SameSite)
|
||||
|
||||
explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray());
|
||||
QNetworkCookie(const QNetworkCookie &other);
|
||||
@ -79,6 +87,8 @@ public:
|
||||
void setSecure(bool enable);
|
||||
bool isHttpOnly() const;
|
||||
void setHttpOnly(bool enable);
|
||||
SameSite sameSite() const;
|
||||
void setSameSite(SameSite sameSite);
|
||||
|
||||
bool isSessionCookie() const;
|
||||
QDateTime expirationDate() const;
|
||||
|
@ -53,24 +53,25 @@
|
||||
|
||||
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
||||
#include "QtCore/qdatetime.h"
|
||||
#include "QtNetwork/qnetworkcookie.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QNetworkCookiePrivate: public QSharedData
|
||||
{
|
||||
public:
|
||||
inline QNetworkCookiePrivate() : secure(false), httpOnly(false) { }
|
||||
QNetworkCookiePrivate() = default;
|
||||
static QList<QNetworkCookie> parseSetCookieHeaderLine(const QByteArray &cookieString);
|
||||
|
||||
QDateTime expirationDate;
|
||||
QString domain;
|
||||
QString path;
|
||||
QString comment;
|
||||
QByteArray sameSite;
|
||||
QByteArray name;
|
||||
QByteArray value;
|
||||
bool secure;
|
||||
bool httpOnly;
|
||||
QNetworkCookie::SameSite sameSite = QNetworkCookie::SameSite::Default;
|
||||
bool secure = false;
|
||||
bool httpOnly = false;
|
||||
};
|
||||
|
||||
static inline bool isLWS(char c)
|
||||
|
@ -44,6 +44,8 @@ private slots:
|
||||
|
||||
void parseMultipleCookies_data();
|
||||
void parseMultipleCookies();
|
||||
|
||||
void sameSite();
|
||||
};
|
||||
|
||||
void tst_QNetworkCookie::getterSetter()
|
||||
@ -683,5 +685,16 @@ void tst_QNetworkCookie::parseMultipleCookies()
|
||||
QCOMPARE(result, expectedCookies);
|
||||
}
|
||||
|
||||
void tst_QNetworkCookie::sameSite()
|
||||
{
|
||||
QList<QNetworkCookie> result = QNetworkCookie::parseCookies(QByteArrayLiteral("a=b;domain=qt-project.org"));
|
||||
QCOMPARE(result.first().sameSite(), QNetworkCookie::SameSite::Default);
|
||||
result = QNetworkCookie::parseCookies(QByteArrayLiteral("a=b;domain=qt-project.org;samesite=strict"));
|
||||
QCOMPARE(result.first().sameSite(), QNetworkCookie::SameSite::Strict);
|
||||
result = QNetworkCookie::parseCookies(QByteArrayLiteral("a=b;domain=qt-project.org;samesite=none;secure"));
|
||||
QCOMPARE(result.first().sameSite(), QNetworkCookie::SameSite::None);
|
||||
QCOMPARE(result.first().toRawForm(), QByteArrayLiteral("a=b; secure; SameSite=None; domain=qt-project.org"));
|
||||
|
||||
}
|
||||
QTEST_MAIN(tst_QNetworkCookie)
|
||||
#include "tst_qnetworkcookie.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user