Making XSRFSecure and XSRFHttpOnly Configurable

This commit is contained in:
Ming Deng 2021-01-18 21:27:50 +08:00
parent 19e6ba8e7c
commit 4ea052602a
8 changed files with 60 additions and 25 deletions

View File

@ -6,10 +6,11 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/toolbox" "github.com/astaxie/beego/toolbox"
) )
@ -151,12 +152,12 @@ func TestHealthCheckHandlerDefault(t *testing.T) {
func TestBuildHealthCheckResponseList(t *testing.T) { func TestBuildHealthCheckResponseList(t *testing.T) {
healthCheckResults := [][]string{ healthCheckResults := [][]string{
[]string{ {
"error", "error",
"Database", "Database",
"Error occurred while starting the db", "Error occurred whie starting the db",
}, },
[]string{ {
"success", "success",
"Cache", "Cache",
"Cache started successfully", "Cache started successfully",
@ -230,10 +231,18 @@ func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
t.Errorf("invalid response map length: got %d want %d", t.Errorf("invalid response map length: got %d want %d",
len(decodedResponseBody), len(expectedResponseBody)) len(decodedResponseBody), len(expectedResponseBody))
} }
assert.Equal(t, len(expectedResponseBody), len(decodedResponseBody))
assert.Equal(t, 2, len(decodedResponseBody))
if !reflect.DeepEqual(decodedResponseBody, expectedResponseBody) { var database, cache map[string]interface{}
t.Errorf("handler returned unexpected body: got %v want %v", if decodedResponseBody[0]["message"] == "database" {
decodedResponseBody, expectedResponseBody) database = decodedResponseBody[0]
cache = decodedResponseBody[1]
} else {
database = decodedResponseBody[1]
cache = decodedResponseBody[0]
} }
assert.Equal(t, expectedResponseBody[0], database)
assert.Equal(t, expectedResponseBody[1], cache)
} }

View File

@ -33,8 +33,8 @@ import (
// Config is the main struct for BConfig // Config is the main struct for BConfig
type Config struct { type Config struct {
AppName string //Application name AppName string // Application name
RunMode string //Running Mode: dev | prod RunMode string // Running Mode: dev | prod
RouterCaseSensitive bool RouterCaseSensitive bool
ServerName string ServerName string
RecoverPanic bool RecoverPanic bool
@ -92,6 +92,8 @@ type WebConfig struct {
EnableXSRF bool EnableXSRF bool
XSRFKey string XSRFKey string
XSRFExpire int XSRFExpire int
XSRFSecure bool
XSRFHttpOnly bool
Session SessionConfig Session SessionConfig
} }
@ -115,8 +117,8 @@ type SessionConfig struct {
// LogConfig holds Log related config // LogConfig holds Log related config
type LogConfig struct { type LogConfig struct {
AccessLogs bool AccessLogs bool
EnableStaticLogs bool //log static files requests default: false EnableStaticLogs bool // log static files requests default: false
AccessLogsFormat string //access log format: JSON_FORMAT, APACHE_FORMAT or empty string AccessLogsFormat string // access log format: JSON_FORMAT, APACHE_FORMAT or empty string
FileLineNum bool FileLineNum bool
Outputs map[string]string // Store Adaptor : config Outputs map[string]string // Store Adaptor : config
} }
@ -215,7 +217,7 @@ func newBConfig() *Config {
RecoverFunc: recoverPanic, RecoverFunc: recoverPanic,
CopyRequestBody: false, CopyRequestBody: false,
EnableGzip: false, EnableGzip: false,
MaxMemory: 1 << 26, //64MB MaxMemory: 1 << 26, // 64MB
EnableErrorsShow: true, EnableErrorsShow: true,
EnableErrorsRender: true, EnableErrorsRender: true,
Listen: Listen{ Listen: Listen{
@ -256,6 +258,8 @@ func newBConfig() *Config {
EnableXSRF: false, EnableXSRF: false,
XSRFKey: "beegoxsrf", XSRFKey: "beegoxsrf",
XSRFExpire: 0, XSRFExpire: 0,
XSRFSecure: false,
XSRFHttpOnly: false,
Session: SessionConfig{ Session: SessionConfig{
SessionOn: false, SessionOn: false,
SessionProvider: "memory", SessionProvider: "memory",
@ -263,7 +267,7 @@ func newBConfig() *Config {
SessionGCMaxLifetime: 3600, SessionGCMaxLifetime: 3600,
SessionProviderConfig: "", SessionProviderConfig: "",
SessionDisableHTTPOnly: false, SessionDisableHTTPOnly: false,
SessionCookieLifeTime: 0, //set cookie default is the browser life SessionCookieLifeTime: 0, // set cookie default is the browser life
SessionAutoSetCookie: true, SessionAutoSetCookie: true,
SessionDomain: "", SessionDomain: "",
SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
@ -355,7 +359,7 @@ func assignConfig(ac config.Configer) error {
} }
} }
//init log // init log
logs.Reset() logs.Reset()
for adaptor, config := range BConfig.Log.Outputs { for adaptor, config := range BConfig.Log.Outputs {
err := logs.SetLogger(adaptor, config) err := logs.SetLogger(adaptor, config)
@ -394,7 +398,7 @@ func assignSingleConfig(p interface{}, ac config.Configer) {
pf.SetBool(ac.DefaultBool(name, pf.Bool())) pf.SetBool(ac.DefaultBool(name, pf.Bool()))
case reflect.Struct: case reflect.Struct:
default: default:
//do nothing here // do nothing here
} }
} }

View File

@ -145,12 +145,22 @@ func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interf
} }
// XSRFToken creates a xsrf token string and returns. // XSRFToken creates a xsrf token string and returns.
func (ctx *Context) XSRFToken(key string, expire int64) string { // others[0] bool secure
// others[1] bool http-only
func (ctx *Context) XSRFToken(key string, expire int64, others...interface{}) string {
if ctx._xsrfToken == "" { if ctx._xsrfToken == "" {
token, ok := ctx.GetSecureCookie(key, "_xsrf") token, ok := ctx.GetSecureCookie(key, "_xsrf")
if !ok { if !ok {
token = string(utils.RandomCreateBytes(32)) token = string(utils.RandomCreateBytes(32))
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "", true, true) secure := false
if len(others) > 0 {
secure = others[0].(bool)
}
httpOnly := false
if len(others) > 1{
httpOnly = others[1].(bool)
}
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "", secure, httpOnly)
} }
ctx._xsrfToken = token ctx._xsrfToken = token
} }

View File

@ -49,6 +49,6 @@ func TestXsrfReset_01(t *testing.T) {
} }
ck := c.ResponseWriter.Header().Get("Set-Cookie") ck := c.ResponseWriter.Header().Get("Set-Cookie")
assert.True(t, strings.Contains(ck, "Secure")) assert.False(t, strings.Contains(ck, "Secure"))
assert.True(t, strings.Contains(ck, "HttpOnly")) assert.False(t, strings.Contains(ck, "HttpOnly"))
} }

View File

@ -154,7 +154,6 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface
fmt.Fprintf(&b, "; HttpOnly") fmt.Fprintf(&b, "; HttpOnly")
} }
} }
output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String()) output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String())
} }

View File

@ -680,7 +680,8 @@ func (c *Controller) XSRFToken() string {
if c.XSRFExpire > 0 { if c.XSRFExpire > 0 {
expire = int64(c.XSRFExpire) expire = int64(c.XSRFExpire)
} }
c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKey, expire) c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKey, expire,
BConfig.WebConfig.XSRFSecure, BConfig.WebConfig.XSRFHttpOnly)
} }
return c._xsrfToken return c._xsrfToken
} }

8
go.mod
View File

@ -7,9 +7,9 @@ require (
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737
github.com/casbin/casbin v1.7.0 github.com/casbin/casbin v1.7.0
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 // indirect github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32 // indirect
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect
github.com/elastic/go-elasticsearch/v6 v6.8.5 github.com/elastic/go-elasticsearch/v6 v6.8.5
github.com/elazarl/go-bindata-assetfs v1.0.0 github.com/elazarl/go-bindata-assetfs v1.0.0
github.com/go-redis/redis v6.14.2+incompatible github.com/go-redis/redis v6.14.2+incompatible
@ -29,7 +29,7 @@ require (
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8
) )

12
go.sum
View File

@ -26,10 +26,18 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d h1:OMrhQqj1QCyDT2sxHCDjE+k8aMdn2ngTCGG7g4wrdLo= github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d h1:OMrhQqj1QCyDT2sxHCDjE+k8aMdn2ngTCGG7g4wrdLo=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17 h1:1ZELwRDUvpBpmgKSIUP6VMW1jIehzD0sCdWxRyejegw=
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 h1:8s2l8TVUwMXl6tZMe3+hPCRJ25nQXiA3d1x622JtOqc= github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 h1:8s2l8TVUwMXl6tZMe3+hPCRJ25nQXiA3d1x622JtOqc=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/gomemcached v0.1.1 h1:xCS8ZglJDhrlQg3jmK7Rn1V8f7bPjXABLC05CgLQauc=
github.com/couchbase/gomemcached v0.1.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32 h1:xnKbM9umdDcpWfEsJzVqRf5PGnIMbiZj2OmDYbleQjM=
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a h1:Y5XsLCEhtEI8qbD9RP3Qlv5FXdTDHxZM9UPUnMRgBp8= github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a h1:Y5XsLCEhtEI8qbD9RP3Qlv5FXdTDHxZM9UPUnMRgBp8=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 h1:4KDlx3vjalrHD/EfsjCpV91HNX3JPaIqRtt83zZ7x+Y=
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ= github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -162,6 +170,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -178,10 +188,12 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=