sessions

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2020 License: MIT Imports: 14 Imported by: 142

README

Sessions GoDoc Go Report Card Build Status License

A minimalist and lightweight HTTP session cookie implementation for Go 1.11+. Session cookies are encrypted and authenticated using nacl/secretbox.

Example Usage

package main

import (
	"net/http"
	"time"

	"github.com/golangcollege/sessions"
)

var session *sessions.Session
var secret = []byte("u46IpCV9y5Vlur8YvODJEhgOY8m9JVE4")

func main() {
	// Initialize and configure new session instance, passing in a 32 byte
	// long secret key (which is used to encrypt and authenticate the
	// session data).
	session = sessions.New(secret)
	session.Lifetime = 3 * time.Hour

	mux := http.NewServeMux()
	mux.HandleFunc("/put", putHandler)
	mux.HandleFunc("/get", getHandler)

	// Wrap your handlers with the session middleware.
	http.ListenAndServe(":4000", session.Enable(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
	// Use the Put() method to store a new key and associated value in the
	// session data.
	session.Put(r, "msg", "Hello world")
	w.WriteHeader(200)
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    // Use the GetString() method helper to retrieve the value associated with
    // a key and convert it to a string. The empty string is returned if the
    // key does not exist in the session data.
	msg := session.GetString(r, "msg")
	w.Write([]byte(msg))
}

Configuring sessions

When setting up a session instance you can specify a mixture of options, or none at all if you're happy with the defaults.

session = sessions.New([]byte("u46IpCV9y5Vlur8YvODJEhgOY8m9JVE4"))

// Domain sets the 'Domain' attribute on the session cookie. By default
// it will be set to the domain name that the cookie was issued from.
session.Domain = "example.org"

// HttpOnly sets the 'HttpOnly' attribute on the session cookie. The
// default value is true.
session.HttpOnly = false

// Lifetime sets the maximum length of time that a session is valid for
// before it expires. The lifetime is an 'absolute expiry' which is set when
// the session is first created and does not change. The default value is 24
// hours.
session.Lifetime = 10*time.Minute

// Path sets the 'Path' attribute on the session cookie. The default value
// is "/". Passing the empty string "" will result in it being set to the
// path that the cookie was issued from.
session.Path = "/account"

// Persist sets whether the session cookie should be persistent or not
// (i.e. whether it should be retained after a user closes their browser).
// The default value is true, which means that the session cookie will not
// be destroyed when the user closes their browser and the appropriate
// 'Expires' and 'MaxAge' values will be added to the session cookie.
session.Persist = false

// Secure sets the 'Secure' attribute on the session cookie. The default
// value is false. It's recommended that you set this to true and serve all
// requests over HTTPS in production environments.
session.Secure = true

// SameSite controls the value of the 'SameSite' attribute on the session
// cookie. By default this is set to 'SameSite=Lax'. If you want no SameSite
// attribute or value in the session cookie then you should set this to 0.
session.SameSite = http.SameSiteStrictMode

// ErrorHandler allows you to control behaviour when an error is encountered
// loading or writing the session cookie. By default the client is sent a
// generic "500 Internal Server Error" response and the actual error message
// is logged using the standard logger. If a custom ErrorHandler function is
// provided then control will be passed to this instead.
session.ErrorHandler  = func(http.ResponseWriter, *http.Request, error) {
	log.Println(err.Error())
    http.Error(w, "Sorry, the application encountered an error", 500)
}
Key rotation

Secret key rotation is supported. An arbitrary number of old secret keys can be provided when initializing a new session instance, like so:

secretKey := []byte("Nrqe6etTZ68GymwxsgpjqwecHqyKLQrr")
oldSecretKey := []byte("TSV2GUduLGYwMkVcssFrHwCHXLhfBH5e")
veryOldSecretKey := []byte("mtuKkskgHwfJzzP56apvNWzrbqfKHvTB")

session = sessions.New(secretKey, oldSecretKey, veryOldSecretKey)
session.Lifetime = 3 * time.Hour

When a session cookie is received from a client, all secret keys are looped through to try to decode the session data. When sending the session cookie to a client the first secret key is used to encrypt the session data.

Managing session data

Adding data
  • Put() — Add a key and corresponding value to the session data.

Important: Because session data is encrypted, signed and stored in a cookie, and cookies are limited to 4096 characters in length, storing large amounts of data may result in a ErrCookieTooLong error.

Fetching data
  • Get() — Fetch the value for a given key from the session data. The returned type is interface{} so will usually need to be type asserted before use.

  • GetBool() — Fetch a bool value for a given key from the session data.

  • GetBytes() — Fetch a byte slice ([]byte) value for a given key from the session data.

  • GetFloat() — Fetch a float64 value for a given key from the session data.

  • GetInt() — Fetch a int value for a given key from the session data.

  • GetString() — Fetch a string value for a given key from the session data.

  • GetTime() — Fetch a time.Time value for a given key from the session data.

  • Pop() — Fetch the value for a given key and then delete it from the session data. The returned type is interface{} so will usually need to be type asserted before use.

  • PopBool() — Fetch a bool value for a given key and then delete it from the session data.

  • PopBytes() — Fetch a byte slice ([]byte) value for a given key and then delete it from the session data.

  • PopFloat() — Fetch a float64 value for a given key and then delete it from the session data.

  • PopInt() — Fetch a int value for a given key and then delete it from the session data.

  • PopString() — Fetch a string value for a given key and then delete it from the session data.

  • PopTime() — Fetch a time.Time value for a given key and then delete it from the session data.

Deleting data
  • Remove() — Deletes a specific key and value from the session data.
  • Destroy() — Destroy the current session. The session data is deleted from memory and the client is instructed to delete the session cookie.
Other
  • Exists() — Returns true if a given key exists in the session data.
  • Keys() — Returns a slice of all keys in the session data.
Custom data types

Behind the scenes SCS uses gob encoding to store custom data types. For this to work properly:

  • Your custom type must first be registered with the encoding/gob package.
  • The fields of your custom types must be exported.

For example:

package main

import (
    "encoding/gob"
    "errors"
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/golangcollege/sessions"
)

var session *sessions.Session
var secret = []byte("u46IpCV9y5Vlur8YvODJEhgOY8m9JVE4")

// Note that the fields on the custom type are all exported.
type User struct {
    Name  string
    Email string
}

func main() {
    // Register the type with the encoding/gob package.
    gob.Register(User{})

    session = sessions.New(secret)
    session.Lifetime = 3 * time.Hour

    mux := http.NewServeMux()
    mux.HandleFunc("/put", putHandler)
    mux.HandleFunc("/get", getHandler)
    http.ListenAndServe(":4000", session.Enable(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
    user := User{"Alice", "alice@example.com"}
    session.Put(r, "user", user)
    w.WriteHeader(200)
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    user, ok := session.Get(r, "user").(User)
    if !ok {
        log.Println(errors.New("type assertion to User failed"))
        http.Error(w, http.StatusText(500), 500)
        return
    }

    fmt.Fprintf(w, "Name: %s, Email: %s", user.Name, user.Email)
}

Documentation

Overview

Package sessions provides a minimalist and lightweight HTTP session cookie implementation for Go. Session cookies are encrypted and authenticated using nacl/secretbox.

Example usage:

package main

import (
	"net/http"
	"time"

	"github.com/golangcollege/sessions"
)

var session *sessions.Session
var secret = []byte("u46IpCV9y5Vlur8YvODJEhgOY8m9JVE4")

func main() {
	session = sessions.New(secret)
	session.Lifetime = 3 * time.Hour

	mux := http.NewServeMux()
	mux.HandleFunc("/put", putHandler)
	mux.HandleFunc("/get", getHandler)
	http.ListenAndServe(":4000", session.Enable(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
	session.Put(r, "msg", "Hello world")
	w.WriteHeader(200)
}

func getHandler(w http.ResponseWriter, r *http.Request) {
	msg := session.GetString(r, "msg")
	w.Write([]byte(msg))
}

Index

Constants

This section is empty.

Variables

View Source
var ErrCookieTooLong = errors.New("session: cookie length greater than 4096 bytes")

Functions

func MockRequest added in v1.1.0

func MockRequest(r *http.Request) *http.Request

Types

type Session

type Session struct {
	// Domain sets the 'Domain' attribute on the session cookie. By default
	// it will be set to the domain name that the cookie was issued from.
	Domain string

	// HttpOnly sets the 'HttpOnly' attribute on the session cookie. The
	// default value is true.
	HttpOnly bool

	// Lifetime sets the maximum length of time that a session is valid for
	// before it expires. The lifetime is an 'absolute expiry' which is set when
	// the session is first created and does not change. The default value is 24
	// hours.
	Lifetime time.Duration

	// Path sets the 'Path' attribute on the session cookie. The default value
	// is "/". Passing the empty string "" will result in it being set to the
	// path that the cookie was issued from.
	Path string

	// Persist sets whether the session cookie should be persistent or not
	// (i.e. whether it should be retained after a user closes their browser).
	// The default value is true, which means that the session cookie will not
	// be destroyed when the user closes their browser and the appropriate
	// 'Expires' and 'MaxAge' values will be added to the session cookie.
	Persist bool

	// Secure sets the 'Secure' attribute on the session cookie. The default
	// value is false. It's recommended that you set this to true and serve all
	// requests over HTTPS in production environments.
	Secure bool

	// SameSite controls the value of the 'SameSite' attribute on the session
	// cookie. By default this is set to 'SameSite=Lax'. If you want no SameSite
	// attribute or value in the session cookie then you should set this to 0.
	SameSite http.SameSite

	// ErrorHandler allows you to control behaviour when an error is encountered
	// loading or writing the session cookie. By default the client is sent a
	// generic "500 Internal Server Error" response and the actual error message
	// is logged using the standard logger. If a custom ErrorHandler function is
	// provided then control will be passed to this instead.
	ErrorHandler func(http.ResponseWriter, *http.Request, error)
	// contains filtered or unexported fields
}

Session holds the configuration settings that you want to use for your sessions.

func New

func New(key []byte, oldKeys ...[]byte) *Session

New initializes a new Session object to hold the configuration settings for your sessions.

The key parameter is the secret you want to use to authenticate and encrypt session cookies. It should be exactly 32 bytes long.

Optionally, the variadic oldKeys parameter can be used to provide an arbitrary number of old Keys. This can be used to ensure that valid cookies continue to work correctly after key rotation.

func (*Session) Destroy

func (s *Session) Destroy(r *http.Request)

Destroy deletes the current session. The session data is deleted from memory and the client is instructed to delete the session cookie.

Any further operations on the session data *within the same request cycle* will result in a panic.

func (*Session) Enable

func (s *Session) Enable(next http.Handler) http.Handler

Enable is middleware which loads and saves session data to and from the session cookie. You should use this middleware to wrap ALL handlers which need to access to the session data. A common way to do this is to wrap your servemux.

Note that session cookies are only sent to the client when the session data has been modified.

func (*Session) Exists

func (s *Session) Exists(r *http.Request, key string) bool

Exists returns true if the given key is present in the session data.

func (*Session) Get

func (s *Session) Get(r *http.Request, key string) interface{}

Get returns the value for a given key from the session data. The return value has the type interface{} so will usually need to be type asserted before you can use it. For example:

foo, ok := session.Get(r, "foo").(string)
if !ok {
	return errors.New("type assertion to string failed")
}

Note: Alternatives are the GetString(), GetInt(), GetBytes() and other helper methods which wrap the type conversion for common types.

func (*Session) GetBool

func (s *Session) GetBool(r *http.Request, key string) bool

GetBool returns the bool value for a given key from the session data. The zero value for a bool (false) is returned if the key does not exist or the value could not be type asserted to a bool.

func (*Session) GetBytes

func (s *Session) GetBytes(r *http.Request, key string) []byte

GetBytes returns the byte slice ([]byte) value for a given key from the session cache. The zero value for a slice (nil) is returned if the key does not exist or could not be type asserted to []byte.

func (*Session) GetFloat

func (s *Session) GetFloat(r *http.Request, key string) float64

GetFloat returns the float64 value for a given key from the session data. The zero value for an float64 (0) is returned if the key does not exist or the value could not be type asserted to a float64.

func (*Session) GetInt

func (s *Session) GetInt(r *http.Request, key string) int

GetInt returns the int value for a given key from the session data. The zero value for an int (0) is returned if the key does not exist or the value could not be type asserted to an int.

func (*Session) GetString

func (s *Session) GetString(r *http.Request, key string) string

GetString returns the string value for a given key from the session data. The zero value for a string ("") is returned if the key does not exist or the value could not be type asserted to a string.

func (*Session) GetTime

func (s *Session) GetTime(r *http.Request, key string) time.Time

GetTime returns the time.Time value for a given key from the session data. The zero value for a time.Time object is returned if the key does not exist or the value could not be type asserted to a time.Time. This can be tested with the time.IsZero() method.

func (*Session) Keys

func (s *Session) Keys(r *http.Request) []string

Keys returns a slice of all key names present in the session data, sorted alphabetically. If the cache contains no data then an empty slice will be returned.

func (*Session) Pop

func (s *Session) Pop(r *http.Request, key string) interface{}

Pop acts like a one-time Get. It returns the value for a given key from the session data and deletes the key and value from the session data. The return value has the type interface{} so will usually need to be type asserted before you can use it.

func (*Session) PopBool

func (s *Session) PopBool(r *http.Request, key string) bool

PopBool returns the bool value for a given key and then deletes it from the session data. The zero value for a bool (false) is returned if the key does not exist or the value could not be type asserted to a bool.

func (*Session) PopBytes

func (s *Session) PopBytes(r *http.Request, key string) []byte

PopBytes returns the byte slice ([]byte) value for a given key and then deletes it from the from the session data. The zero value for a slice (nil) is returned if the key does not exist or could not be type asserted to []byte.

func (*Session) PopFloat

func (s *Session) PopFloat(r *http.Request, key string) float64

PopFloat returns the float64 value for a given key and then deletes it from the session data. The zero value for an float64 (0) is returned if the key does not exist or the value could not be type asserted to a float64.

func (*Session) PopInt

func (s *Session) PopInt(r *http.Request, key string) int

PopInt returns the int value for a given key and then deletes it from the session data. The zero value for an int (0) is returned if the key does not exist or the value could not be type asserted to an int.

func (*Session) PopString

func (s *Session) PopString(r *http.Request, key string) string

PopString returns the string value for a given key and then deletes it from the session data. The zero value for a string ("") is returned if the key does not exist or the value could not be type asserted to a string.

func (*Session) PopTime

func (s *Session) PopTime(r *http.Request, key string) time.Time

PopTime returns the time.Time value for a given key and then deletes it from the session data. The zero value for a time.Time object is returned if the key does not exist or the value could not be type asserted to a time.Time.

func (*Session) Put

func (s *Session) Put(r *http.Request, key string, val interface{})

Put adds a key and corresponding value to the session data. Any existing value for the key will be replaced.

func (*Session) Remove

func (s *Session) Remove(r *http.Request, key string)

Remove deletes the given key and corresponding value from the session data. If the key is not present this operation is a no-op.

Jump to

Keyboard shortcuts

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