diff --git a/context/context.go b/context/context.go index c6517e62..90d21c9c 100644 --- a/context/context.go +++ b/context/context.go @@ -20,6 +20,7 @@ import ( "time" "github.com/astaxie/beego/middleware" + "github.com/astaxie/beego/utils" ) // Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter. @@ -29,6 +30,7 @@ type Context struct { Output *BeegoOutput Request *http.Request ResponseWriter http.ResponseWriter + _xsrf_token string } // Redirect does redirection to localurl with http header status code. @@ -113,3 +115,35 @@ func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interf cookie := strings.Join([]string{vs, timestamp, sig}, "|") ctx.Output.Cookie(name, cookie, others...) } + +// XsrfToken creates a xsrf token string and returns. +func (ctx *Context) XsrfToken(key string, expire int64) string { + if ctx._xsrf_token == "" { + token, ok := ctx.GetSecureCookie(key, "_xsrf") + if !ok { + token = string(utils.RandomCreateBytes(32)) + ctx.SetSecureCookie(key, "_xsrf", token, expire) + } + ctx._xsrf_token = token + } + return ctx._xsrf_token +} + +// CheckXsrfCookie checks xsrf token in this request is valid or not. +// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken" +// or in form field value named as "_xsrf". +func (ctx *Context) CheckXsrfCookie() bool { + token := ctx.Input.Query("_xsrf") + if token == "" { + token = ctx.Request.Header.Get("X-Xsrftoken") + } + if token == "" { + token = ctx.Request.Header.Get("X-Csrftoken") + } + if token == "" { + ctx.Abort(403, "'_xsrf' argument missing from POST") + } else if ctx._xsrf_token != token { + ctx.Abort(403, "XSRF cookie does not match POST argument") + } + return true +} diff --git a/controller.go b/controller.go index f486bc36..782d8731 100644 --- a/controller.go +++ b/controller.go @@ -25,7 +25,6 @@ import ( "github.com/astaxie/beego/context" "github.com/astaxie/beego/session" - "github.com/astaxie/beego/utils" ) //commonly used mime-types @@ -477,18 +476,13 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter // XsrfToken creates a xsrf token string and returns. func (c *Controller) XsrfToken() string { if c._xsrf_token == "" { - token, ok := c.GetSecureCookie(XSRFKEY, "_xsrf") - if !ok { - var expire int64 - if c.XSRFExpire > 0 { - expire = int64(c.XSRFExpire) - } else { - expire = int64(XSRFExpire) - } - token = string(utils.RandomCreateBytes(32)) - c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire) + var expire int64 + if c.XSRFExpire > 0 { + expire = int64(c.XSRFExpire) + } else { + expire = int64(XSRFExpire) } - c._xsrf_token = token + c._xsrf_token = c.Ctx.XsrfToken(XSRFKEY, expire) } return c._xsrf_token } @@ -500,19 +494,7 @@ func (c *Controller) CheckXsrfCookie() bool { if !c.EnableXSRF { return true } - token := c.GetString("_xsrf") - if token == "" { - token = c.Ctx.Request.Header.Get("X-Xsrftoken") - } - if token == "" { - token = c.Ctx.Request.Header.Get("X-Csrftoken") - } - if token == "" { - c.Ctx.Abort(403, "'_xsrf' argument missing from POST") - } else if c._xsrf_token != token { - c.Ctx.Abort(403, "XSRF cookie does not match POST argument") - } - return true + return c.Ctx.CheckXsrfCookie() } // XsrfFormHtml writes an input field contains xsrf token value.