Go iris中如何正确使用securecookie加密验证

使用cookie认证登录,是很多网站常用的方式,因为它可持久化,方便用户下次再次无感知登陆使用系统,但是cookie的安全常常令人担忧,Go iris框架提供了cookie加密解密的入口方法和加密解密的函数类型,方便用户自行引入自己的函数包。securecookie包对经过身份验证和可选加密的cookie值进行编码和解码(Encode,Decode),securecookie不能伪造,因为它们的值是使用HMAC验证的。 加密后,恶意手法也无法访问内容。

1、一般用法
安装包
$ go get github.com/gorilla/securecookie

要使用它,首先要创建一个新的SecureCookie实例:
var hashKey = []byte("very-secret")
var blockKey = []byte("a-lot-secret")
var s = securecookie.New(hashKey, blockKey)

hashKey是必需的,用于使用HMAC验证cookie值。 建议使用32或64字节的密钥。

blockKey是可选的,用于加密cookie值 - 将其设置为nil以不使用加密。如果设置,则长度必须对应于加密算法的块大小。对于默认使用的AES,有效长度为16,24或32字节,用于选择AES-128,AES-192或AES-256。

使用s.Encode(name, value)对cookie进行编码
func SetCookieHandler(w http.ResponseWriter, r *http.Request) {
value := map[string]string{
"foo": "bar",
}
if encoded, err := s.Encode("cookie-name", value); err == nil {
cookie := &http.Cookie{
Name: "cookie-name",
Value: encoded,
Path: "/",
}
http.SetCookie(w, cookie)
}
}

使用s.Decode(name, value, interface{})解码
func ReadCookieHandler(w http.ResponseWriter, r *http.Request) {
if cookie, err := r.Cookie("cookie-name"); err == nil {
value := make(map[string]string)
if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil {
fmt.Fprintf(w, "The value of foo is %q", value["foo"])
}
}
}

我们存储了一个map [string]字符串,但是securecookie可以保存任何可以使用encoding/gob编码的值。要存储自定义类型,必须首先使用gob.Register()注册它们。 对于基本类型,这不是必需的;它开箱即用。

2、结合iris框架的使用方式
package main

import (
    "github.com/kataras/iris"

    "github.com/gorilla/securecookie"
)

var (
    // hashKey是必需的,用于使用HMAC验证cookie值。 建议使用32或64字节的密钥。
    hashKey = []byte("the-big-and-secret-fash-key-here")
    // blockKey是可选的,用于加密cookie值 - 将其设置为nil以不使用加密。
    // 如果设置,则长度必须对应于加密算法的块大小。
    // 对于默认使用的AES,有效长度为16,24或32字节,用于选择AES-128,AES-192或AES-256。
    blockKey = []byte("lot-secret-of-characters-big-too")
    sc = securecookie.New(hashKey, blockKey)
)

func newApp() *iris.Application {
    app := iris.New()

    // Set A Cookie.
    app.Get("/cookies/{name}/{value}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        value := ctx.Params().Get("value")

        ctx.SetCookieKV(name, value, iris.CookieEncode(sc.Encode)) // <--

        ctx.Writef("cookie added: %s = %s", name, value)
    })

    // Retrieve A Cookie.
    app.Get("/cookies/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")

        value := ctx.GetCookie(name, iris.CookieDecode(sc.Decode)) // <--

        ctx.WriteString(value)
    })

    // Delete A Cookie.
    app.Delete("/cookies/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")

        ctx.RemoveCookie(name) // <--

        ctx.Writef("cookie %s removed", name)
    })

    return app
}

func main() {
    app := newApp()
    app.Run(iris.Addr(":8080"))
}

iris框架中提供了两个函数类型,它们是iris.CookieEncode(encode CookieEncoder),iris.CookieDecode(decode CookieDecoder)的参数类型
CookieEncoder func(cookieName string, value interface{}) (string, error)
CookieDecoder func(cookieName string, cookieValue string, v interface{}) error

securecookie包提供了两个方法,与上面的函数类型匹配
func (s *SecureCookie) Encode(name string, value interface{}) (string, error)
func (s *SecureCookie) Decode(name, value string, dst interface{}) error

写cookie


读cookie

Posted by 何敏 on 2019/03/19 07:46:37