sessions

package
v0.0.0-...-456eabd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2011 License: BSD-3-Clause Imports: 15 Imported by: 0

Documentation

Overview

Package gorilla/sessions provides cookie sessions and infrastructure for custom session back-ends.

The key features are:

* Dead simple basic API: use it as an easy way to set signed (and optionally encrypted) cookies.

* Advanced API for custom back-ends: built-in support for custom storage systems; session store interface and helper functions; encoder interface and default implementation with customizable cryptography methods (thanks to Go interfaces).

* Conveniences: flash messages (session values that last until read); built-in mechanism to rotate authentication and encryption keys; multiple sessions per request, even using different back-ends; easy way to switch session persistency (aka "remember me") and set other attributes.

The most basic example to retrieve a session is to call sessions.Session() passing the current request. For example, in a handler:

func MyHandler(w http.ResponseWriter, r *http.Request) {
	if session, err := sessions.Session(r); err == nil {
		session["foo"] = "bar"
		session["baz"] = 128
		sessions.Save(r, w)
	}
}

The above snippet is "gorilla/sessions in a nutshell": a session is a simple map[string]interface{} returned from sessions.Session(). It stores any values that can be encoded using gob. After we set some values, we call sessions.Save() passing the current request and response.

Side note about "any values that can be encoded using gob": to store special structures in a session, we must register them using gob.Register() first. For basic types this is not needed; it works out of the box.

Is it that simple? Well, almost. Before we can use sessions, we must define a secret key to be used for authentication, and optionally an encryption key. They are both set calling SetStoreKeys() and should be done at initialization time:

func init() {
	sessions.SetStoreKeys("cookie",
						  []byte("my-hmac-key"),
						  []byte("my-aes-key"))
}

The first argument is the name used to register the session store. By default a "cookie" store is registered and available for use, so we use that name.

The second argument is the secret key used to authenticate the session cookie using HMAC. It is required; if no authentication key is set sessions can't be read or written (and a call to sessions.Session() will return an error).

The third argument is the encryption key; it is optional and can be omitted. For the cookie store, setting this will encrypt the contents stored in the cookie; otherwise the contents can be read, although not forged.

Side note about the encryption key: if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes. Otherwise a block can't be created and sessions won't work.

Exposing the contents of a session is not a big deal in many cases, like when we store a simple username or user id, but to to store sensitive information using the cookie store, we must set an encryption key. For custom stores that only set a random session id in the cookie, encryption is not needed.

And this is all you need to know about the basic usage. More advanced options are explained below.

Sometimes we may want to change authentication and/or encryption keys without breaking existing sessions. We can do this setting multiple authentication and encryption keys, in pairs, to be tested in order:

sessions.SetStoreKeys("cookie",
					  []byte("my-hmac-key"),
					  []byte("my-aes-key"),
					  []byte("my-previous-hmac-key"),
					  []byte("my-previous-aes-key"))

New sessions will be saved using the first pair. Old sessions can still be read because the first pair will fail, and the second will be tested. This makes it easy to "rotate" secret keys and still be able to validate existing sessions. Note: for all pairs the encryption key is optional; set it to nil and encryption won't be used.

Back to how sessions are retrieved.

Sessions are named. When we get a session calling sessions.Session(request), we are implicitly requesting a session using the default key ("s") and store (the CookieSessionStore). This is just a convenience; we can have as many sessions as needed, just passing different session keys. For example:

if authSession, err := sessions.Session(r, "auth"); err == nil {
	userId = authSession["userId"]
	// ...
}

Here we requested a session explicitly naming it "auth". It will be saved separately. This can be used as a convenient way to save signed cookies, and is also how we access multiple sessions per request.

Session stores also have a name, and need to be registered to be available. The default session store uses authenticated (and optionally encrypted) cookies, and is registered with the name "cookie". To use a custom session back-end, we first register it in the SessionFactory, then pass its name as the third argument to sessions.Session().

For the sake of demonstration, let's pretend that we defined a store called MemcacheSessionStore. First we register it using the "memcache" key. This should be done at initialization time:

func init() {
	sessions.SetStore("memcache", new(MemcacheSessionStore))
}

Then to get a session using memcached, we pass a third argument to sessions.Session(), the store key:

session, err := sessions.Session(r, "mysession", "memcache")

...and it will use the custom back-end we defined, instead of the default "cookie" one. This means that we can use multiple sessions in the same request even using different back-ends.

And how to configure session expiration time, path or other cookie attributes?

By default, session cookies last for a month. This is probably too long for a lot of cases, but it is easy to change this and other attributes during runtime. Just request the session configuration struct and change the variables as needed. The fields are basically a subset of http.Cookie fields. To change MaxAge, we would do:

if config, err = sessions.Config(r); err == nil {
	// Change max-age to 1 week.
	config.MaxAge = 86400 * 7
}

After this, cookies will last for a week only. The Config() function accepts an optional argument besides the request: the session key. If not defined, the configuration for the default session key is returned.

Bonus: flash messages. What are they? It basically means "session values that last until read". The term was popularized by Ruby On Rails a few years back. When we request a flash message, it is removed from the session. We have two convenience functions to read and set them: Flashes() and AddFlash(). Here is an example:

func MyHandler(w http.ResponseWriter, r *http.Request) {
	// Get the previously set flashes, if any.
	if flashes, _ := sessions.Flashes(r); flashes != nil {
		// Just print the flash values.
		fmt.Fprint(w, "%v", flashes)
	} else {
		fmt.Fprint(w, "No flashes found.")
		// Set a new flash.
		sessions.AddFlash(r, "Hello, flash messages world!")
	}
	sessions.Save(r, w)
}

Flash messages are useful to set information to be read after a redirection, usually after form submissions.

Index

Constants

This section is empty.

Variables

View Source
var (
	DefaultSessionKey = "s"
	DefaultStoreKey   = "cookie"
	DefaultFlashesKey = "_flash"
	// All errors.
	ErrEncoding       = errors.New("The value could not be encoded.")
	ErrDecoding       = errors.New("The value could not be decoded.")
	ErrAuthentication = errors.New("The value could not be verified using HMAC.")
	ErrDecryption     = errors.New("The value could not be decrypted.")
	ErrMaxLength      = errors.New("The value exceeds the maximum allowed length.")
	ErrBadTimestamp   = errors.New("Invalid timestamp.")
	ErrNewTimestamp   = errors.New("The value has a newer timestamp than expected.")
	ErrOldTimestamp   = errors.New("The value has an expired timestamp.")
	ErrMissingHash    = errors.New("A hash is required to create and verify values using HMAC.")
	ErrMissingHashKey = errors.New("Authentication secret can't be nil.")
	ErrNoSession      = errors.New("No session found for the given key.")
	ErrNoFlashes      = errors.New("No flashes found for the given key.")
	ErrNoStore        = errors.New("No store found for the given key.")
	ErrStoreMismatch  = errors.New("A session with the given key already exists using a different store.")
	ErrBadIdLength    = errors.New("Session id length must be greater than zero.")
)
View Source
var DefaultSessionConfig = &SessionConfig{
	Path:     "/",
	Domain:   "",
	MaxAge:   86400 * 30,
	Secure:   false,
	HttpOnly: false,
}

DefaultSessionConfig is the session configuration used when none is set.

View Source
var DefaultSessionFactory = new(SessionFactory)

DefaultSessionFactory is the default factory for session requests.

Functions

func AddFlash

func AddFlash(r *http.Request, value interface{},
	vars ...string) (bool, error)

AddFlash adds a flash message.

The variadic arguments are optional: (flashKey, sessionKey, storeKey). If not defined or empty the default values are used.

func Encode

func Encode(s SessionStore, key string, value SessionData) (string, error)

Encode encodes a session value for a session store.

func Flashes

func Flashes(r *http.Request, vars ...string) ([]interface{}, error)

Flashes returns an array of flash messages, if any.

The variadic arguments are optional: (flashKey, sessionKey, storeKey). If not defined or empty the default values are used.

func GenerateSessionId

func GenerateSessionId(length int) (string, error)

GenerateSessionId generates a random session id with the given length.

func Save

func Save(r *http.Request, w http.ResponseWriter) []error

Save saves all sessions accessed during the request.

func SerializeSessionData

func SerializeSessionData(session SessionData) ([]byte, error)

SerializeSessionData serializes a session value using gob.

func SetCookie

func SetCookie(s SessionStore, w http.ResponseWriter, key string,
	info *SessionInfo) (bool, error)

SetCookie sets a session cookie using the user-defined configuration.

Custom backends will only store a session id in the cookie.

func SetDefaultConfig

func SetDefaultConfig(config *SessionConfig)

SetDefaultConfig sets the default session configuration used by the factory.

func SetStore

func SetStore(key string, store SessionStore)

SetStore registers a session store for the given key.

func SetStoreKeys

func SetStoreKeys(key string, pairs ...[]byte) (bool, error)

SetStoreKeys defines authentication and encryption keys for the given store.

See SessionFactory.SetStoreKeys.

Types

type CookieSessionStore

type CookieSessionStore struct {
	// contains filtered or unexported fields
}

CookieSessionStore is the default session store.

It stores the session data in authenticated and, optionally, encrypted cookies.

func (*CookieSessionStore) Encoders

func (s *CookieSessionStore) Encoders() []SessionEncoder

Encoders returns the encoders for this store.

func (*CookieSessionStore) Load

func (s *CookieSessionStore) Load(r *http.Request, key string,
	info *SessionInfo)

Load loads a session for the given key.

func (*CookieSessionStore) Save

Save saves the session in the response.

func (*CookieSessionStore) SetEncoders

func (s *CookieSessionStore) SetEncoders(encoders ...SessionEncoder)

SetEncoders sets a group of encoders in the store.

type Encoder

type Encoder struct {
	// Required, used for authentication.
	// Set it to, e.g.: hmac.NewSHA256([]byte("very-secret-key"))
	Hash hash.Hash
	// Optional, used for encryption.
	// Set it to, e.g.: aes.NewCipher([]byte("16-length-secret-key"))
	Block cipher.Block
	// Optional, to restrict minimum age, in seconds, for the timestamp value.
	// Set it to 0 for no restriction.
	MinAge int64
	// Optional, to restrict maximum age, in seconds, for the timestamp value.
	// Set it to 0 for no restriction.
	MaxAge int64
	// Optional, to restrict length of values to be decoded.
	// Set it to, e.g.: 1024 (conservative) or 4096 (maximum cookie size).
	MaxLength int
	// For testing purposes, the function that returns the current timestamp.
	// If not set, it will use time.UTC().Seconds().
	TimeFunc func() int64
}

Encoder encodes and decodes session values.

It is a default SessionEncoder implementation available for all session stores. It performs up to four operations in both ways:

1. Serialization: encodes to and from gob.

2. Encryption (optional): if the Block field is set, it is used to encrypt and decrypt the value in CTR mode.

3. Authentication: creates and verifies HMACs. The Hash field is required: if not set, sessions can't be read or written.

4. Encoding: converts to and from a format suitable for cookie transmition.

Multiple encoders can be added to a session store to allow secret keys rotation.

func (*Encoder) Decode

func (s *Encoder) Decode(key, value string) (SessionData, error)

Decode decodes a session value.

It decodes, verifies a message authentication code, optionally decrypts and finally deserializes the value.

func (*Encoder) Encode

func (s *Encoder) Encode(key string, value SessionData) (rv string, err error)

Encode encodes a session value.

It serializes, optionally encrypts, creates a message authentication code and finally encodes the value in a format suitable for cookie transmition.

type SessionConfig

type SessionConfig struct {
	Path   string
	Domain string
	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'.
	// MaxAge>0 means Max-Age attribute present and given in seconds.
	MaxAge   int
	Secure   bool
	HttpOnly bool
}

SessionConfig stores configuration for each session.

Fields are a subset of http.Cookie fields.

func Config

func Config(r *http.Request, key ...string) (*SessionConfig, error)

Config returns the configuration for a given session.

The key argument is optional; if not set it'll use the default session key.

func DefaultConfig

func DefaultConfig() *SessionConfig

DefaultConfig returns the default session configuration used by the factory.

type SessionData

type SessionData map[string]interface{}

The type used to store session values.

func Decode

func Decode(s SessionStore, key, value string) (SessionData, error)

Decode decodes a session value for a session store.

func DeserializeSessionData

func DeserializeSessionData(value []byte) (data SessionData, err error)

DeserializeSessionData deserializes a session value using gob.

func GetCookie

func GetCookie(s SessionStore, r *http.Request, key string) SessionData

GetCookie returns the contents from a session cookie.

If the session is invalid, it will return an empty SessionData.

func Session

func Session(r *http.Request, vars ...string) (SessionData, error)

Session returns a session for the current request.

The variadic arguments are optional: (sessionKey, storeKey). They are used to load a different session key or use a session store other than the default one. If not defined or empty the defaults are used.

type SessionEncoder

type SessionEncoder interface {
	Encode(key string, value SessionData) (string, error)
	Decode(key, value string) (SessionData, error)
}

SessionEncoder defines an interface to encode and decode session values.

type SessionFactory

type SessionFactory struct {
	// contains filtered or unexported fields
}

SessionFactory registers configuration and stores available for use.

func (*SessionFactory) AddFlash

func (f *SessionFactory) AddFlash(r *http.Request, value interface{},
	vars ...string) (bool, error)

AddFlash adds a flash message.

The variadic arguments are optional: (flashKey, sessionKey, storeKey). If not defined or empty the default values are used.

func (*SessionFactory) Config

func (f *SessionFactory) Config(r *http.Request,
	key ...string) (*SessionConfig, error)

Config returns the configuration for a given session.

The key argument is optional; if not set it'll use the default session key.

func (*SessionFactory) DefaultConfig

func (f *SessionFactory) DefaultConfig() *SessionConfig

DefaultConfig returns the default session configuration used by the factory.

func (*SessionFactory) Flashes

func (f *SessionFactory) Flashes(r *http.Request,
	vars ...string) ([]interface{}, error)

Flashes returns an array of flash messages, if any.

The variadic arguments are optional: (flashKey, sessionKey, storeKey). If not defined or empty the default values are used.

func (*SessionFactory) Save

Save saves all sessions accessed during the request.

func (*SessionFactory) Session

func (f *SessionFactory) Session(r *http.Request,
	vars ...string) (SessionData, error)

Session returns a session for the current request.

The variadic arguments are optional: (sessionKey, storeKey). They are used to load a different session key or use a session store other than the default one. If not defined or empty the defaults are used.

func (*SessionFactory) SetDefaultConfig

func (f *SessionFactory) SetDefaultConfig(config *SessionConfig)

SetDefaultConfig sets the default session configuration used by the factory.

func (*SessionFactory) SetStore

func (f *SessionFactory) SetStore(key string, store SessionStore)

SetStore registers a session store for the given key.

func (*SessionFactory) SetStoreKeys

func (f *SessionFactory) SetStoreKeys(key string,
	pairs ...[]byte) (bool, error)

SetStoreKeys defines authentication and encryption keys for the given store.

This is a convenience to set secret keys for the available stores. It sets authentication hashes using HMAC-SHA-256 and encryption blocks using AES. For custom hash or encryption methods, call SessionStore.SetEncoders() directly.

A store must be registered using the given key before this is called.

Keys are defined in pairs: one for authentication and the other for encryption. The encryption key can be set to nil or omitted in the last pair, but the authentication key is required in all pairs.

Multiple pairs are accepted to allow key rotation, but the common case is to set a single authentication key and optionally an encryption key.

The encryption key, if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.

func (*SessionFactory) Store

func (f *SessionFactory) Store(key string) (SessionStore, error)

Store returns a session store for the given key.

type SessionInfo

type SessionInfo struct {
	Data   SessionData
	Store  SessionStore
	Config SessionConfig
}

SessionInfo stores internal references for a given session.

type SessionStore

type SessionStore interface {
	Load(r *http.Request, key string, info *SessionInfo)
	Save(r *http.Request, w http.ResponseWriter, key string, info *SessionInfo) (bool, error)
	Encoders() []SessionEncoder
	SetEncoders(encoders ...SessionEncoder)
}

SessionStore defines an interface for session stores.

func Store

func Store(key string) (SessionStore, error)

Store returns a session store for the given key.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL