Feature #7814 » 0001-Add-SameSite-support-to-setCookie.patch
| src/Wt/WApplication.C | ||
|---|---|---|
|
const std::string& value, int maxAge,
|
||
|
const std::string& domain,
|
||
|
const std::string& path,
|
||
|
bool secure)
|
||
|
bool secure,
|
||
|
CookieSameSite sameSite)
|
||
|
{
|
||
|
WDateTime expires = WDateTime::currentDateTime();
|
||
|
expires = expires.addSecs(maxAge);
|
||
|
session_->renderer().setCookie(name, value, expires, domain, path, secure);
|
||
|
session_->renderer().setCookie(name, value, expires, domain, path, secure, sameSite);
|
||
|
}
|
||
|
#ifndef WT_TARGET_JAVA
|
||
| ... | ... | |
|
const WDateTime& expires,
|
||
|
const std::string& domain,
|
||
|
const std::string& path,
|
||
|
bool secure)
|
||
|
bool secure,
|
||
|
CookieSameSite sameSite)
|
||
|
{
|
||
|
session_->renderer().setCookie(name, value, expires, domain, path, secure);
|
||
|
session_->renderer().setCookie(name, value, expires, domain, path, secure, sameSite);
|
||
|
}
|
||
|
#endif // WT_TARGET_JAVA
|
||
| src/Wt/WApplication.h | ||
|---|---|---|
|
*/
|
||
|
void setCookie(const std::string& name, const std::string& value,
|
||
|
int maxAge, const std::string& domain = "",
|
||
|
const std::string& path = "", bool secure = false);
|
||
|
const std::string& path = "", bool secure = false,
|
||
|
CookieSameSite sameSite = CookieSameSite::Lax);
|
||
|
#ifndef WT_TARGET_JAVA
|
||
|
void setCookie(const std::string& name, const std::string& value,
|
||
|
const WDateTime& expires, const std::string& domain = "",
|
||
|
const std::string& path = "", bool secure = false);
|
||
|
const std::string& path = "", bool secure = false,
|
||
|
CookieSameSite sameSite = CookieSameSite::Lax);
|
||
|
#endif // WT_TARGET_JAVA
|
||
|
/*! \brief Removes a cookie.
|
||
| src/Wt/WGlobal.h | ||
|---|---|---|
|
};
|
||
|
#endif // WT_TARGET_JAVA
|
||
|
/*! \brief Enumeration that specifies the SameSite values for HTTP Cookies
|
||
|
*
|
||
|
* \sa WApplication::setCookie()
|
||
|
*/
|
||
|
enum class CookieSameSite {
|
||
|
None, //!< Sent in all contexts (note: generally not allowed if secure not specified)
|
||
|
Lax, //!< Sent for first-party and top-level GET from third-party
|
||
|
Strict //!< Sent for first-party only
|
||
|
};
|
||
|
}
|
||
|
#endif // WGLOBALS_H_
|
||
| src/web/WebRenderer.C | ||
|---|---|---|
|
LOGGER("WebRenderer");
|
||
|
WebRenderer::CookieValue::CookieValue()
|
||
|
: secure(false)
|
||
|
: secure(false),
|
||
|
sameSite(CookieSameSite::Lax)
|
||
|
{ }
|
||
|
WebRenderer::CookieValue::CookieValue(const std::string& v,
|
||
|
const std::string& p,
|
||
|
const std::string& d,
|
||
|
const WDateTime& e,
|
||
|
bool s)
|
||
|
bool s,
|
||
|
CookieSameSite sameSite)
|
||
|
: value(v),
|
||
|
path(p),
|
||
|
domain(d),
|
||
|
expires(e),
|
||
|
secure(s)
|
||
|
secure(s),
|
||
|
sameSite(sameSite)
|
||
|
{ }
|
||
|
WebRenderer::WebRenderer(WebSession& session)
|
||
| ... | ... | |
|
void WebRenderer::setCookie(const std::string name, const std::string value,
|
||
|
const WDateTime& expires,
|
||
|
const std::string domain, const std::string path,
|
||
|
bool secure)
|
||
|
bool secure, CookieSameSite sameSite)
|
||
|
{
|
||
|
cookiesToSet_[name] = CookieValue(value, path, domain, expires, secure);
|
||
|
if (sameSite == CookieSameSite::None and !secure) {
|
||
|
LOG_WARN("setCookie: called with SameSite::None, but not secure (cookie name: " << name << ")");
|
||
|
}
|
||
|
cookiesToSet_[name] = CookieValue(value, path, domain, expires, secure, sameSite);
|
||
|
}
|
||
|
void WebRenderer::setCaching(WebResponse& response, bool allowCache)
|
||
| ... | ... | |
|
if (cookie.secure)
|
||
|
header << " secure;";
|
||
|
switch (cookie.sameSite) {
|
||
|
case CookieSameSite::None:
|
||
|
header << " SameSite=None;";
|
||
|
break;
|
||
|
case CookieSameSite::Lax:
|
||
|
header << " SameSite=Lax;";
|
||
|
break;
|
||
|
case CookieSameSite::Strict:
|
||
|
header << " SameSite=Strict;";
|
||
|
break;
|
||
|
}
|
||
|
response.addHeader("Set-Cookie", header.str());
|
||
|
}
|
||
|
cookiesToSet_.clear();
|
||
| src/web/WebRenderer.h | ||
|---|---|---|
|
void setCookie(const std::string name, const std::string value,
|
||
|
const WDateTime& expires, const std::string domain,
|
||
|
const std::string path, bool secure);
|
||
|
const std::string path, bool secure,
|
||
|
CookieSameSite = CookieSameSite::Lax);
|
||
|
bool preLearning() const { return learning_; }
|
||
|
void learningIncomplete();
|
||
| ... | ... | |
|
std::string domain;
|
||
|
WDateTime expires;
|
||
|
bool secure;
|
||
|
CookieSameSite sameSite;
|
||
|
CookieValue();
|
||
|
CookieValue(const std::string& v, const std::string& p,
|
||
|
const std::string& d, const WDateTime& e, bool secure);
|
||
|
const std::string& d, const WDateTime& e, bool secure,
|
||
|
CookieSameSite sameSite);
|
||
|
};
|
||
|
WebSession& session_;
|
||
| src/web/WebSession.C | ||
|---|---|---|
|
sessionIdCookie_ = WRandom::generateId();
|
||
|
sessionIdCookieChanged_ = true;
|
||
|
renderer().setCookie("Wt" + sessionIdCookie_, "1", Wt::WDateTime(), "", "",
|
||
|
env_->urlScheme() == "https");
|
||
|
env_->urlScheme() == "https", CookieSameSite::Strict);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
if (!useUrlRewriting()) {
|
||
|
std::string cookieName = env_->deploymentPath();
|
||
|
renderer().setCookie(cookieName, sessionId_, WDateTime(), "", "", env_->urlScheme() == "https");
|
||
|
renderer().setCookie(cookieName, sessionId_, WDateTime(), "", "",
|
||
|
env_->urlScheme() == "https", CookieSameSite::Strict);
|
||
|
}
|
||
|
if (controller_->configuration().sessionIdCookie()) {
|
||
|
sessionIdCookie_ = WRandom::generateId();
|
||
|
sessionIdCookieChanged_ = true;
|
||
|
renderer().setCookie("Wt" + sessionIdCookie_, "1", WDateTime(), "", "",
|
||
|
env_->urlScheme() == "https");
|
||
|
env_->urlScheme() == "https", CookieSameSite::Strict);
|
||
|
}
|
||
|
}
|
||
|
#endif // WT_TARGET_JAVA
|
||
| src/web/skeleton/Boot.js | ||
|---|---|---|
|
_$_$if_COOKIE_CHECKS_$_();
|
||
|
// client-side cookie support
|
||
|
var testcookie='jscookietest=valid';
|
||
|
var testcookie='jscookietest=valid;SameSite=Lax';
|
||
|
doc.cookie=testcookie;
|
||
|
no_replace = no_replace ||
|
||
|
(_$_USE_COOKIES_$_ && doc.cookie.indexOf(testcookie) != -1);
|
||
|
doc.cookie=testcookie+';expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||
|
doc.cookie=testcookie+';expires=Thu, 01 Jan 1970 00:00:00 GMT;SameSite=Lax';
|
||
|
// server-side cookie support
|
||
|
doc.cookie='WtTestCookie=ok;path=/;expires=' + inOneSecond.toGMTString();
|
||
|
doc.cookie='WtTestCookie=ok;path=/;expires=' + inOneSecond.toGMTString() + ';SameSite=Lax';
|
||
|
_$_$endif_$_();
|
||
|
// hash to query
|
||
| ... | ... | |
|
if (!htmlHistory && canonicalUrl.length > 1) {
|
||
|
_$_$if_HYBRID_$_();
|
||
|
var pathcookie='WtInternalPath=' + escape(_$_INTERNAL_PATH_$_)
|
||
|
+ ';path=/;expires=' + inOneSecond.toGMTString();
|
||
|
+ ';path=/;expires=' + inOneSecond.toGMTString() + ';SameSite=Lax';
|
||
|
doc.cookie=pathcookie;
|
||
|
_$_$endif_$_();
|
||
|
/* Otherwise we do not get a page reload */
|
||