From dd45be693a8913551ebc07852e223eba7508aa5b Mon Sep 17 00:00:00 2001 From: wja513 Date: Sat, 17 Jul 2021 02:08:17 +0800 Subject: [PATCH] cookie: add possibility to disable same site attribute (#1428) * fix some old browsers cann't set the cookie if it contains SameSite property. * add "SameSite" attribute constants and test case. Co-authored-by: wangjiangao --- ctx.go | 7 ++-- ctx_test.go | 23 ++++++++++--- helpers.go | 99 +++++++++++++++++++++++++++++------------------------ 3 files changed, 77 insertions(+), 52 deletions(-) diff --git a/ctx.go b/ctx.go index 0950d0b5..fbbed651 100644 --- a/ctx.go +++ b/ctx.go @@ -33,7 +33,6 @@ const maxParams = 30 const queryTag = "query" - // Ctx represents the Context which hold the HTTP request and response. // It has methods for the request query string, parameters, body, HTTP headers and so on. type Ctx struct { @@ -364,10 +363,12 @@ func (c *Ctx) Cookie(cookie *Cookie) { fcookie.SetHTTPOnly(cookie.HTTPOnly) switch utils.ToLower(cookie.SameSite) { - case "strict": + case CookieSameSiteStrictMode: fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode) - case "none": + case CookieSameSiteNoneMode: fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode) + case CookieSameSiteDisabled: + fcookie.SetSameSite(fasthttp.CookieSameSiteDisabled) default: fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode) } diff --git a/ctx_test.go b/ctx_test.go index d2830ab9..ba14244a 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -524,16 +524,31 @@ func Test_Ctx_Cookie(t *testing.T) { var dst []byte dst = expire.In(time.UTC).AppendFormat(dst, time.RFC1123) httpdate := strings.Replace(string(dst), "UTC", "GMT", -1) - c.Cookie(&Cookie{ + cookie := &Cookie{ Name: "username", Value: "john", Expires: expire, - }) + //SameSite: CookieSameSiteStrictMode, // default is "lax" + } + c.Cookie(cookie) expect := "username=john; expires=" + httpdate + "; path=/; SameSite=Lax" utils.AssertEqual(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) - c.Cookie(&Cookie{SameSite: "strict"}) - c.Cookie(&Cookie{SameSite: "none"}) + expect = "username=john; expires=" + httpdate + "; path=/" + cookie.SameSite = CookieSameSiteDisabled + c.Cookie(cookie) + utils.AssertEqual(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) + + expect = "username=john; expires=" + httpdate + "; path=/; SameSite=Strict" + cookie.SameSite = CookieSameSiteStrictMode + c.Cookie(cookie) + utils.AssertEqual(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) + + expect = "username=john; expires=" + httpdate + "; path=/; secure; SameSite=None" + cookie.Secure = true + cookie.SameSite = CookieSameSiteNoneMode + c.Cookie(cookie) + utils.AssertEqual(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) } // go test -v -run=^$ -bench=Benchmark_Ctx_Cookie -benchmem -count=4 diff --git a/helpers.go b/helpers.go index 559bea38..c3a9cdb4 100644 --- a/helpers.go +++ b/helpers.go @@ -631,51 +631,51 @@ const ( HeaderCrossOriginResourcePolicy = "Cross-Origin-Resource-Policy" HeaderExpectCT = "Expect-CT" // Deprecated: use HeaderPermissionsPolicy instead - HeaderFeaturePolicy = "Feature-Policy" - HeaderPermissionsPolicy = "Permissions-Policy" - HeaderPublicKeyPins = "Public-Key-Pins" - HeaderPublicKeyPinsReportOnly = "Public-Key-Pins-Report-Only" - HeaderStrictTransportSecurity = "Strict-Transport-Security" - HeaderUpgradeInsecureRequests = "Upgrade-Insecure-Requests" - HeaderXContentTypeOptions = "X-Content-Type-Options" - HeaderXDownloadOptions = "X-Download-Options" - HeaderXFrameOptions = "X-Frame-Options" - HeaderXPoweredBy = "X-Powered-By" - HeaderXXSSProtection = "X-XSS-Protection" - HeaderLastEventID = "Last-Event-ID" - HeaderNEL = "NEL" - HeaderPingFrom = "Ping-From" - HeaderPingTo = "Ping-To" - HeaderReportTo = "Report-To" - HeaderTE = "TE" - HeaderTrailer = "Trailer" - HeaderTransferEncoding = "Transfer-Encoding" - HeaderSecWebSocketAccept = "Sec-WebSocket-Accept" - HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions" - HeaderSecWebSocketKey = "Sec-WebSocket-Key" - HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol" - HeaderSecWebSocketVersion = "Sec-WebSocket-Version" - HeaderAcceptPatch = "Accept-Patch" - HeaderAcceptPushPolicy = "Accept-Push-Policy" - HeaderAcceptSignature = "Accept-Signature" - HeaderAltSvc = "Alt-Svc" - HeaderDate = "Date" - HeaderIndex = "Index" - HeaderLargeAllocation = "Large-Allocation" - HeaderLink = "Link" - HeaderPushPolicy = "Push-Policy" - HeaderRetryAfter = "Retry-After" - HeaderServerTiming = "Server-Timing" - HeaderSignature = "Signature" - HeaderSignedHeaders = "Signed-Headers" - HeaderSourceMap = "SourceMap" - HeaderUpgrade = "Upgrade" - HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control" - HeaderXPingback = "X-Pingback" - HeaderXRequestID = "X-Request-ID" - HeaderXRequestedWith = "X-Requested-With" - HeaderXRobotsTag = "X-Robots-Tag" - HeaderXUACompatible = "X-UA-Compatible" + HeaderFeaturePolicy = "Feature-Policy" + HeaderPermissionsPolicy = "Permissions-Policy" + HeaderPublicKeyPins = "Public-Key-Pins" + HeaderPublicKeyPinsReportOnly = "Public-Key-Pins-Report-Only" + HeaderStrictTransportSecurity = "Strict-Transport-Security" + HeaderUpgradeInsecureRequests = "Upgrade-Insecure-Requests" + HeaderXContentTypeOptions = "X-Content-Type-Options" + HeaderXDownloadOptions = "X-Download-Options" + HeaderXFrameOptions = "X-Frame-Options" + HeaderXPoweredBy = "X-Powered-By" + HeaderXXSSProtection = "X-XSS-Protection" + HeaderLastEventID = "Last-Event-ID" + HeaderNEL = "NEL" + HeaderPingFrom = "Ping-From" + HeaderPingTo = "Ping-To" + HeaderReportTo = "Report-To" + HeaderTE = "TE" + HeaderTrailer = "Trailer" + HeaderTransferEncoding = "Transfer-Encoding" + HeaderSecWebSocketAccept = "Sec-WebSocket-Accept" + HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions" + HeaderSecWebSocketKey = "Sec-WebSocket-Key" + HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol" + HeaderSecWebSocketVersion = "Sec-WebSocket-Version" + HeaderAcceptPatch = "Accept-Patch" + HeaderAcceptPushPolicy = "Accept-Push-Policy" + HeaderAcceptSignature = "Accept-Signature" + HeaderAltSvc = "Alt-Svc" + HeaderDate = "Date" + HeaderIndex = "Index" + HeaderLargeAllocation = "Large-Allocation" + HeaderLink = "Link" + HeaderPushPolicy = "Push-Policy" + HeaderRetryAfter = "Retry-After" + HeaderServerTiming = "Server-Timing" + HeaderSignature = "Signature" + HeaderSignedHeaders = "Signed-Headers" + HeaderSourceMap = "SourceMap" + HeaderUpgrade = "Upgrade" + HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control" + HeaderXPingback = "X-Pingback" + HeaderXRequestID = "X-Request-ID" + HeaderXRequestedWith = "X-Requested-With" + HeaderXRobotsTag = "X-Robots-Tag" + HeaderXUACompatible = "X-UA-Compatible" ) // Network types that are commonly used @@ -692,3 +692,12 @@ const ( StrDeflate = "deflate" StrBrotli = "brotli" ) + +// Cookie SameSite +// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7 +const ( + CookieSameSiteDisabled = "disabled" // not in RFC, just control "SameSite" attribute will not be set. + CookieSameSiteLaxMode = "lax" + CookieSameSiteStrictMode = "strict" + CookieSameSiteNoneMode = "none" +)