summaryrefslogtreecommitdiff
path: root/securecookie.go
diff options
context:
space:
mode:
authorMatt Silverlock <matt@eatsleeprepeat.net>2015-05-16 20:50:49 +0300
committerMatt Silverlock <matt@eatsleeprepeat.net>2015-05-20 23:49:45 +0300
commit3c76054b695479521e1fffdc338a4a0c0c617730 (patch)
tree17c21131640ad8736c88b7d8d2c6464aaf588540 /securecookie.go
parent2e358078af96ec4fe5b962482254f80aabc35f64 (diff)
Added a JSON encoder/decoder to securecookie.
A new "Serializer" interface with serialize/deserialize methods allows custom encoders to be specified. encoding/gob remains the default for compatibility/ease-of-use reasons, but the (often faster) encoding/json is now an option. Fixed typo - TestEncription => TestEncryption
Diffstat (limited to 'securecookie.go')
-rw-r--r--securecookie.go61
1 files changed, 55 insertions, 6 deletions
diff --git a/securecookie.go b/securecookie.go
index 1b7acf8..8d8c623 100644
--- a/securecookie.go
+++ b/securecookie.go
@@ -14,6 +14,7 @@ import (
"crypto/subtle"
"encoding/base64"
"encoding/gob"
+ "encoding/json"
"errors"
"fmt"
"hash"
@@ -44,6 +45,7 @@ type Codec interface {
// GenerateRandomKey(). The key length must correspond to the block size
// of the encryption algorithm. For AES, used by default, valid lengths are
// 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
+// The default encoder used for cookie serialization is encoding/gob.
func New(hashKey, blockKey []byte) *SecureCookie {
s := &SecureCookie{
hashKey: hashKey,
@@ -51,6 +53,7 @@ func New(hashKey, blockKey []byte) *SecureCookie {
hashFunc: sha256.New,
maxAge: 86400 * 30,
maxLength: 4096,
+ sz: GobEncoder{},
}
if hashKey == nil {
s.err = errHashKeyNotSet
@@ -72,11 +75,28 @@ type SecureCookie struct {
maxAge int64
minAge int64
err error
+ sz Serializer
// For testing purposes, the function that returns the current timestamp.
// If not set, it will use time.Now().UTC().Unix().
timeFunc func() int64
}
+// Serializer provides an interface for providing custom serializers for cookie
+// values.
+type Serializer interface {
+ Serialize(src interface{}) ([]byte, error)
+ Deserialize(src []byte, dst interface{}) error
+}
+
+// GobEncoder encodes cookie values using encoding/gob. This is the simplest
+// serializer and can handle complex types via gob.Register.
+type GobEncoder struct{}
+
+// JSONEncoder encodes cookie values using encoding/json. Users who wish to
+// encode complex types need to satisfy the json.Marshaller and
+// json.Unmarshaller interfaces.
+type JSONEncoder struct{}
+
// MaxLength restricts the maximum length, in bytes, for the cookie value.
//
// Default is 4096, which is the maximum value accepted by Internet Explorer.
@@ -123,6 +143,15 @@ func (s *SecureCookie) BlockFunc(f func([]byte) (cipher.Block, error)) *SecureCo
return s
}
+// Encoding sets the encoding/serialization method for cookies.
+//
+// Default is encoding/gob.
+func (s *SecureCookie) SetSerializer(sz Serializer) *SecureCookie {
+ s.sz = sz
+
+ return s
+}
+
// Encode encodes a cookie value.
//
// It serializes, optionally encrypts, signs with a message authentication code, and
@@ -143,7 +172,7 @@ func (s *SecureCookie) Encode(name string, value interface{}) (string, error) {
var err error
var b []byte
// 1. Serialize.
- if b, err = serialize(value); err != nil {
+ if b, err = s.sz.Serialize(value); err != nil {
return "", err
}
// 2. Encrypt (optional).
@@ -226,7 +255,7 @@ func (s *SecureCookie) Decode(name, value string, dst interface{}) error {
}
}
// 6. Deserialize.
- if err = deserialize(b, dst); err != nil {
+ if err = s.sz.Deserialize(b, dst); err != nil {
return err
}
// Done.
@@ -300,8 +329,8 @@ func decrypt(block cipher.Block, value []byte) ([]byte, error) {
// Serialization --------------------------------------------------------------
-// serialize encodes a value using gob.
-func serialize(src interface{}) ([]byte, error) {
+// Serialize encodes a value using gob.
+func (e GobEncoder) Serialize(src interface{}) ([]byte, error) {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
if err := enc.Encode(src); err != nil {
@@ -310,8 +339,8 @@ func serialize(src interface{}) ([]byte, error) {
return buf.Bytes(), nil
}
-// deserialize decodes a value using gob.
-func deserialize(src []byte, dst interface{}) error {
+// Deserialize decodes a value using gob.
+func (e GobEncoder) Deserialize(src []byte, dst interface{}) error {
dec := gob.NewDecoder(bytes.NewBuffer(src))
if err := dec.Decode(dst); err != nil {
return err
@@ -319,6 +348,26 @@ func deserialize(src []byte, dst interface{}) error {
return nil
}
+// Serialize encodes a value using encoding/json.
+func (e JSONEncoder) Serialize(src interface{}) ([]byte, error) {
+ buf := new(bytes.Buffer)
+ enc := json.NewEncoder(buf)
+ if err := enc.Encode(src); err != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+// Deserialize decodes a value using encoding/json.
+func (e JSONEncoder) Deserialize(src []byte, dst interface{}) error {
+ dec := json.NewDecoder(bytes.NewReader(src))
+ if err := dec.Decode(dst); err != nil {
+ return err
+ }
+ return nil
+}
+
// Encoding -------------------------------------------------------------------
// encode encodes a value using base64.