From 93e1206d6063181a58af7d59818274269ae36a4c Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 25 Sep 2013 23:05:47 +0800 Subject: [PATCH] xsrf change to randstr and cookie set to security cookie --- beego.go | 2 +- controller.go | 49 ++++++++++++++++++++++---- middleware/i18n.go | 85 +++++++++++++++++++++++++++++++++++++++++++++- utils.go | 11 ++++++ 4 files changed, 138 insertions(+), 9 deletions(-) diff --git a/beego.go b/beego.go index a6132bc7..c58302c3 100644 --- a/beego.go +++ b/beego.go @@ -67,7 +67,7 @@ func Run() { } if SessionOn { - GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath) + GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath, HttpTLS) go GlobalSessions.GC() } diff --git a/controller.go b/controller.go index 31f07188..f036f9cb 100644 --- a/controller.go +++ b/controller.go @@ -304,21 +304,56 @@ func (c *Controller) IsAjax() bool { return c.Ctx.Input.IsAjax() } +func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) { + val := c.Ctx.GetCookie(key) + if val == "" { + return "", false + } + + parts := strings.SplitN(val, "|", 3) + + vs := parts[0] + timestamp := parts[1] + sig := parts[2] + + h := hmac.New(sha1.New, []byte(Secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + + if fmt.Sprintf("%02x", h.Sum(nil)) != sig { + return "", false + } + + ts, _ := strconv.ParseInt(timestamp, 0, 64) + + buf := bytes.NewBufferString(val) + encoder := base64.NewDecoder(base64.StdEncoding, buf) + + res, _ := ioutil.ReadAll(encoder) + return string(res), true +} + +func (c *Controller) SetSecureCookie(Secret, name, val string, age int) { + vs := base64.URLEncoding.EncodeToString([]byte(val)) + timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) + h := hmac.New(sha1.New, []byte(Secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + sig := fmt.Sprintf("%02x", h.Sum(nil)) + cookie := strings.Join([]string{vs, timestamp, sig}, "|") + c.Ctx.SetCookie(name, cookie, age, "/") +} + func (c *Controller) XsrfToken() string { if c._xsrf_token == "" { - token := c.Ctx.GetCookie("_xsrf") - if token == "" { - h := hmac.New(sha1.New, []byte(XSRFKEY)) - fmt.Fprintf(h, "%s:%d", c.Ctx.Request.RemoteAddr, time.Now().UnixNano()) - tok := fmt.Sprintf("%s:%d", h.Sum(nil), time.Now().UnixNano()) - token = base64.URLEncoding.EncodeToString([]byte(tok)) + token, ok := c.GetSecureCookie(XSRFKEY, "_xsrf") + if !ok { expire := 0 if c.XSRFExpire > 0 { expire = c.XSRFExpire } else { expire = XSRFExpire } - c.Ctx.SetCookie("_xsrf", token, expire, "/") + token = GetRandomString(15) + c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire) } c._xsrf_token = token } diff --git a/middleware/i18n.go b/middleware/i18n.go index 5ccdd705..973a4a6f 100644 --- a/middleware/i18n.go +++ b/middleware/i18n.go @@ -1 +1,84 @@ -package middleware \ No newline at end of file +package middleware + +//import ( +// "github.com/astaxie/beego/config" +// "os" +// "path" +//) + +//type Translation struct { +// filetype string +// CurrentLocal string +// Locales map[string]map[string]string +//} + +//func NewLocale(filetype string) *Translation { +// return &Translation{ +// filetype: filetype, +// CurrentLocal: "zh", +// Locales: make(map[string]map[string]string), +// } +//} + +//func (t *Translation) loadTranslations(dirPath string) error { +// dir, err := os.Open(dirPath) +// if err != nil { +// return err +// } +// defer dir.Close() + +// names, err := dir.Readdirnames(-1) +// if err != nil { +// return err +// } + +// for _, name := range names { +// fullPath := path.Join(dirPath, name) + +// fi, err := os.Stat(fullPath) +// if err != nil { +// return err +// } + +// if fi.IsDir() { +// continue +// } else { +// if err := t.loadTranslation(fullPath, name); err != nil { +// return err +// } +// } +// } + +// return nil +//} + +//func (t *Translation) loadTranslation(fullPath, locale string) error { + +// sourceKey2Trans, ok := t.Locales[locale] +// if !ok { +// sourceKey2Trans = make(map[string]string) + +// t.Locales[locale] = sourceKey2Trans +// } + +// for _, m := range trf.Messages { +// if m.Translation != "" { +// sourceKey2Trans[sourceKey(m.Source, m.Context)] = m.Translation +// } +// } + +// return nil +//} + +//func (t *Translation) SetLocale(local string) { +// t.CurrentLocal = local +//} + +//func (t *Translation) Translate(key string) string { +// if ct, ok := t.Locales[t.CurrentLocal]; ok { +// if v, o := ct[key]; o { +// return v +// } +// } +// return key +//} diff --git a/utils.go b/utils.go index ade81e4f..efaf1551 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,7 @@ package beego import ( + "crypto/rand" "fmt" "html/template" "net/url" @@ -362,3 +363,13 @@ func FileExists(path string) (bool, error) { } return false, err } + +func GetRandomString(n int) string { + const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + var bytes = make([]byte, n) + rand.Read(bytes) + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + return string(bytes) +}