abcsessions

package
v2.1.5+incompatible Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2017 License: BSD-3-Clause, BSD-3-Clause Imports: 15 Imported by: 0

README

ABCSessions

License GoDoc Go Report Card

Available Session Storers

  • Disk
  • Memory
  • Redis
  • Cookie

API Operations

Note, you should avoid mixing and matching API calls for key-value versus object. Stick to one mode for every app you generate (either simple sessions using key-value strings and the regular helpers or a custom sessions struct using the object helpers). This is the main API entry point (key-value or object API) to use.

Key-Value string API

These session API endpoints are ideal for apps that only require simple session strings to be stored and not a full custom sessions struct with a lot of differing variables and types.

// Set adds a key-value pair to your session. 
Set(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

// Get retrieves a key-value pair value stored in your session.
Get(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)

// Del deletes a key-value pair from your session.
Del(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) error

// AddFlash adds a flash message key-value pair to your session.
AddFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

// GetFlash retrieves a flash message key-value pair value stored in your session. 
// Note that flash messages are automatically deleted after being retrieved once.
GetFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)
Object API

These session API endpoints are ideal for apps that are best served with a sessions struct opposed to individual strings. This flexibility allows you to define your own custom sessions struct with a range of differing variable types. See examples for Object API usage.

// SetObj adds any object or variable to your session.
SetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, value interface{}) error

// GetObj retrieves an object or variable stored in your session.
GetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, value interface{}) error

// AddFlashObj adds an object as a flash message to your session.
AddFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value interface{}) error

// GetFlashObj retrieves a object as a flash message stored in your session.
// Note that flash messages are automatically deleted after being retrieved once.
GetFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, pointer interface{}) error

Overseer interface

The job of an Overseer is to interface with your storers and manage your session cookies. If you want to work with the session values you probably want to use the higher level API functions listed above, but if you want to work with the session directly you can use these overseer methods.

Resetter

The Overseer interface imbeds the Resetter interface which defines the functions used to reset the expiries of your sessions. This is handled automatically by the ResetMiddleware and is not something that needs to be called directly.

// Set creates or updates a session with a raw value.
Set(w http.ResponseWriter, r *http.Request, value string) error

// Get the raw value stored in a session.
Get(w http.ResponseWriter, r *http.Request) (value string, err error)

// Delete a session and signal the browser to expire the session cookie.
Del(w http.ResponseWriter, r *http.Request) error

// Regenerate a new session ID for your session.
Regenerate(w http.ResponseWriter, r *http.Request) error

// SessionID returns the session ID for your session.
SessionID(w http.ResponseWriter, r *http.Request) (id string, err error)

Storer interface

In the case of session management, "keys" here are synonymous with session IDs. This is as lower level API and generally not used too much, because the above higher-level API functions call these functions. This can be used if you need to deal with the storer directly for whatever reason.

// All retrieves all keys in the store.
All() (keys []string, err error)

// Get retrieves the value stored against a specific key.
Get(key string) (value string, err error)

// Set a key-value pair in the store.
Set(key, value string) error

// Delete a key-value pair from the store.
Del(key string) error

// Reset the expiry of a key in the store.
ResetExpiry(key string) error

Available Overseers

// StorageOverseer is used for all server-side sessions (disk, memory, redis, etc).
NewStorageOverseer(opts CookieOptions, storer Storer) *StorageOverseer

//CookieOverseer is used for client-side only cookie sessions.
NewCookieOverseer(opts CookieOptions, secretKey [32]byte) *CookieOverseer

How does each Storer work?

Disk

Disk sessions store the session as a text file on disk. By default they store in the systems temp directory under a folder that is randomly generated when you generate your app using abcweb app generator command. The file names are the UUIDs of the session. Each time the file is accessed (using Get, Set, manually on disk, or by using the ResetMiddleware) it will reset the access time of the file, which will push back the expiration defined by maxAge. For example, if your maxAge is set to 1 week, and your cleanInterval is set to 2 hours, then every 2 hours the cleaner will find all disk sessions files that have not been accessed for over 1 week and delete them. If the user refreshes a website and you're using the ResetMiddleware then that 1 week timer will be reset. If your maxAge and cleanInterval is set to 0 then these disk session files will permanently persist, however the browser will still expire sessions depending on your cookieOptions maxAge configuration. In a typical (default) setup, cookieOptions will be set to maxAge 0 (expire on browser close), your DiskStorer maxAge will be set to 2 days, and your DiskStorer cleanInterval will be set to 1 hour.

Memory

Memory sessions are stored in memory in a mutex protected map[string]memorySession. The key to the map is the session ID and the memorySession stores the value and expiry of the session. The memory storer also has methods to start and stop a cleaner go routine that will delete expired sessions on an interval that is defined when creating the memory session storer (cleanInterval).

Redis

Redis sessions are stored in a Redis database. Different databases can be used by specifying a different database ID on creation of the storer. Redis handles session expiration automatically.

The cookie storer is intermingled with the CookieOverseer, so to use it you must use the CookieOverseer instead of the StorageOverseer. Cookie sessions are stored in encrypted form (AES-GCM encrypted and base64 encoded) in the clients browser.

Middlewares

Sessions Middleware

The sessions.Middleware is a required component when using this sessions package. The sessions middleware converts the ResponseWriter that is being passed along to your controller into a response type. This type implements the ResponseWriter interface, but its implementation also takes care of writing the cookies in the response objects buffer. These cookies are created as a result of creating/deleting sessions using the sessions library.

Sessions ResetMiddleware

When using the sessions.ResetMiddleware it will reset the expiry of the session of the current user regardless of whether that session is being loaded or modified by your controller. This ensures that users navigating to pages that rely on no session activation (for example a simple about page) will keep their session alive.

Without this middleware, for all storers except the disk storer, your session will only reset the expiry when modifying the session (using a Set call). For the disk storer it will refresh on both a Set and a Get because it relies on file access time.

In the majority of cases the middleware is the best user-experience, and we highly recommend loading this middleware by default. You should load one instance of this middleware for each session overseer you are using.

Error types

If an API operation fails, and you would like to check if it failed due to no session existing (errNoSession type), or the key used in a map-key operation not existing (errNoMapKey type), you can check the error types using the following functions against the errors returned:

// errNoSession is a possible return value of Get and ResetExpiry
IsNoSessionError(err error) bool

// errNoMapKey is a possible return value of abcsessions.Get and abcsessions.GetFlash
// It indicates that the key-value map stored under a session did not have the 
// requested key
IsNoMapKeyError(err error) bool

Examples

Using object helpers

// A session struct you've defined. Can contain anything you like.
type MySession struct {
	Username string
	AccessLevel int
	...
}

err := SetObj(o, w, r, MySession{...})
var mySess MySession

err := GetObj(o, w, r, &mySess)
if IsNoSessionError(err) {
	fmt.Printf("No session found")
}

Using object flash helpers

// A flash struct you've defined. Can contain anything you like.
type FlashError struct {
	Error string
	Code int
}

err := AddFlashObj(o, w, r, "login", &FlashError{...})
var errorObj FlashError

err := GetFlashObj(o, w, r, "login", &errorObj)

Create an Overseer

cookieOverseer := NewCookieOverseer(NewCookieOptions(), []byte("secretkeyhere"))
// Uses default addr of localhost:6379
storer, err := NewDefaultRedisStorer("", "", 0)
if err != nil {
	panic(err)
}

redisOverseer := NewStorageOverseer(NewCookieOptions(), storer)
storer, _ := NewDefaultMemoryStorer()
memoryOverseer := NewStorageOverseer(NewCookieOptions(), storer)

// Start the cleaner go routine
memoryOverseer.StartCleaner()

Handling unexpected errors

// o == overseer instance
val, err := abcsessions.Get(o, w, r, "coolkid")
if err != nil {
	if IsNoSessionError(err) {
		// Maybe you want to redirect? Maybe you want to create a new session?
	} else if IsNoMapKeyError(err) {
		// "coolkid" key didn't exist. Maybe you want to create it?
	} else {
		// Something crazy happened. Panic? Attempt to fix it?
		if err := o.Del(w, r); err != nil {
			panic(err)
		}
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddFlash

func AddFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

AddFlash adds a flash message to the session that will be deleted when it is retrieved with GetFlash

func AddFlashObj

func AddFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value interface{}) error

AddFlashObj adds a flash message to the session that will be deleted when it is retrieved with GetFlash

func Del

func Del(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) error

Del is a JSON helper used for deleting keys from a key-value session values store. Del is a noop on nonexistent keys, but will error if the session does not exist.

func Get

func Get(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)

Get is a JSON helper used for retrieving key-value session values. Get returns the value pointed to by the key of the marshalled map stored in the session.

func GetFlash

func GetFlash(overseer Overseer, w http.ResponseWriter, r *http.Request, key string) (string, error)

GetFlash retrieves a flash message from the session then deletes it

func GetFlashObj

func GetFlashObj(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, pointer interface{}) error

GetFlashObj unmarshals a flash message from the session into the users pointer then deletes it from the session.

func GetObj

func GetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, pointer interface{}) error

GetObj is a JSON helper used for retrieving object or variable session values. GetObj unmarshals the session value into the pointer pointed to by pointer.

func IsNoMapKeyError

func IsNoMapKeyError(err error) bool

IsNoMapKeyError checks an error to see if it means that there was no session map key

func IsNoSessionError

func IsNoSessionError(err error) bool

IsNoSessionError checks an error to see if it means that there was no session

func Middleware

func Middleware(next http.Handler) http.Handler

Middleware converts the ResponseWriter object to a sessionsResponseWriter for buffering cookies across session API requests. The sessionsResponseWriter implements cookieWriter.

If you would also like to reset the users session expiry on each request (recommended), then use MiddlewareWithReset instead.

func Set

func Set(overseer Overseer, w http.ResponseWriter, r *http.Request, key string, value string) error

Set is a JSON helper used for storing key-value session values. Set modifies the marshalled map stored in the session to include the key value pair passed in.

func SetObj

func SetObj(overseer Overseer, w http.ResponseWriter, r *http.Request, value interface{}) error

SetObj is a JSON helper used for storing object or variable session values. Set stores in the session a marshaled version of the passed in value pointed to by value.

Types

type CookieOptions

type CookieOptions struct {
	// Domain is the domain name the cookie is for
	Domain string
	// Path is the URI path the cookie is for
	Path string
	// Name for the session cookie, defaults to "id"
	Name string
	// MaxAge sets the max-age and the expires fields of a cookie
	// A value of 0 means the browser will expire the session on browser close
	MaxAge time.Duration
	// Secure ensures the cookie is only given on https connections
	Secure bool
	// HTTPOnly means the browser will never allow JS to touch this cookie
	HTTPOnly bool
}

CookieOptions for the session cookies themselves. See https://tools.ietf.org/html/rfc6265 for details.

func NewCookieOptions

func NewCookieOptions() CookieOptions

NewCookieOptions gives healthy defaults for session cookies

type CookieOverseer

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

CookieOverseer oversees cookie operations that are encrypted and verified but does store all data client side which means it is a possible attack vector. Uses GCM to verify and encrypt data.

func NewCookieOverseer

func NewCookieOverseer(opts CookieOptions, secretKey []byte) *CookieOverseer

NewCookieOverseer creates an overseer from cookie options and a secret key for use in encryption. Panic's on any errors that deal with cryptography.

func (*CookieOverseer) Del

Del a value from the cookie overseer

func (*CookieOverseer) Get

Get a value from the cookie overseer

func (CookieOverseer) MiddlewareWithReset

func (m CookieOverseer) MiddlewareWithReset(next http.Handler) http.Handler

Middleware converts the ResponseWriter object to a sessionsResponseWriter for buffering cookies across session API requests. The sessionsResponseWriter implements cookieWriter.

MiddlewareWithReset also resets the users session expiry on each request. If you do not want this added functionality use Middleware instead.

func (*CookieOverseer) Regenerate

func (c *CookieOverseer) Regenerate(w http.ResponseWriter, r *http.Request) error

Regenerate for the cookie overseer will panic because cookie sessions do not have session IDs, only values.

func (*CookieOverseer) ResetExpiry

func (c *CookieOverseer) ResetExpiry(w http.ResponseWriter, r *http.Request) error

ResetExpiry resets the age of the session to time.Now(), so that MaxAge calculations are renewed

func (CookieOverseer) ResetMiddleware

func (m CookieOverseer) ResetMiddleware(next http.Handler) http.Handler

ResetMiddleware resets the users session expiry on each request.

Note: Generally you will want to use Middleware or MiddlewareWithReset instead of this middleware, but if you have a requirement to insert a middleware between the sessions Middleware and the sessions ResetMiddleware then you can use the Middleware first, and this one second, as a two-step process, instead of the combined MiddlewareWithReset middleware.

It's also important to note that the sessions Middleware must come BEFORE this middleware in the chain, or you will get a panic.

func (*CookieOverseer) SessionID

func (c *CookieOverseer) SessionID(w http.ResponseWriter, r *http.Request) (string, error)

SessionID for the cookie overseer will panic because cookie sessions do not have session IDs, only values.

func (*CookieOverseer) Set

func (c *CookieOverseer) Set(w http.ResponseWriter, r *http.Request, value string) error

Set a value into the cookie overseer

type DiskStorer

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

DiskStorer is a session storer implementation for saving sessions to disk.

func NewDefaultDiskStorer

func NewDefaultDiskStorer(tmpSubFolder string) (*DiskStorer, error)

NewDefaultDiskStorer returns a DiskStorer object with default values. The default values are: FolderPath: system tmp dir + random folder maxAge: 2 days (clear session stored on server after 2 days) cleanInterval: 1 hour (delete sessions older than maxAge every 1 hour)

func NewDiskStorer

func NewDiskStorer(folderPath string, maxAge, cleanInterval time.Duration) (*DiskStorer, error)

NewDiskStorer initializes and returns a new DiskStorer object. It takes the maxAge of how long each session should live on disk, and a cleanInterval duration which defines how often the clean task should check for maxAge expired sessions to be removed from disk. Persistent storage can be attained by setting maxAge and cleanInterval to zero.

func (*DiskStorer) All

func (d *DiskStorer) All() ([]string, error)

All keys in the disk store

func (*DiskStorer) Clean

func (d *DiskStorer) Clean()

Clean checks all session files on disk to see if they are older than maxAge by checking their access time. If it finds an expired session file it will remove it from disk.

func (*DiskStorer) Del

func (d *DiskStorer) Del(key string) error

Del the session pointed to by the session id key and remove it.

func (*DiskStorer) Get

func (d *DiskStorer) Get(key string) (value string, err error)

Get returns the value string saved in the session pointed to by the session id key.

func (*DiskStorer) ResetExpiry

func (d *DiskStorer) ResetExpiry(key string) error

ResetExpiry resets the expiry of the key

func (*DiskStorer) Set

func (d *DiskStorer) Set(key, value string) error

Set saves the value string to the session pointed to by the session id key.

func (*DiskStorer) StartCleaner

func (d *DiskStorer) StartCleaner()

StartCleaner starts the disk session cleaner go routine. This go routine will delete expired disk sessions on the cleanInterval interval.

func (*DiskStorer) StopCleaner

func (d *DiskStorer) StopCleaner()

StopCleaner stops the cleaner go routine

type MemoryStorer

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

MemoryStorer is a session storer implementation for saving sessions to memory.

func NewDefaultMemoryStorer

func NewDefaultMemoryStorer() (*MemoryStorer, error)

NewDefaultMemoryStorer returns a MemoryStorer object with default values. The default values are: maxAge: 2 days (clear session stored on server after 2 days) cleanInterval: 1 hour (delete sessions older than maxAge every hour)

func NewMemoryStorer

func NewMemoryStorer(maxAge, cleanInterval time.Duration) (*MemoryStorer, error)

NewMemoryStorer initializes and returns a new MemoryStorer object. It takes the maxAge of how long each session should live in memory, and a cleanInterval duration which defines how often the clean task should check for maxAge sessions to be removed from memory. Persistent storage can be attained by setting maxAge and cleanInterval to zero, however the memory will be wiped when the server is restarted.

func (*MemoryStorer) All

func (m *MemoryStorer) All() ([]string, error)

All keys in the memory store

func (*MemoryStorer) Clean

func (m *MemoryStorer) Clean()

Clean checks all sessions in memory to see if they are older than maxAge by checking their expiry. If it finds an expired session it will remove it from memory.

func (*MemoryStorer) Del

func (m *MemoryStorer) Del(key string) error

Del the session pointed to by the session id key and remove it.

func (*MemoryStorer) Get

func (m *MemoryStorer) Get(key string) (value string, err error)

Get returns the value string saved in the session pointed to by the session id key.

func (*MemoryStorer) ResetExpiry

func (m *MemoryStorer) ResetExpiry(key string) error

ResetExpiry resets the expiry of the key

func (*MemoryStorer) Set

func (m *MemoryStorer) Set(key, value string) error

Set saves the value string to the session pointed to by the session id key.

func (*MemoryStorer) StartCleaner

func (m *MemoryStorer) StartCleaner()

StartCleaner starts the memory session cleaner go routine. This go routine will delete expired sessions from the memory map on the cleanInterval interval.

func (*MemoryStorer) StopCleaner

func (m *MemoryStorer) StopCleaner()

StopCleaner stops the cleaner go routine

type Overseer

type Overseer interface {
	Resetter
	// Get the value stored in a session
	Get(w http.ResponseWriter, r *http.Request) (value string, err error)
	// Set creates or updates a session with value
	Set(w http.ResponseWriter, r *http.Request, value string) error
	// Delete a session
	Del(w http.ResponseWriter, r *http.Request) error
	// Regenerate a new session id for your session
	Regenerate(w http.ResponseWriter, r *http.Request) error
	// SessionID returns the session id for your session
	SessionID(w http.ResponseWriter, r *http.Request) (id string, err error)
}

Overseer of session cookies

type RedisStorer

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

RedisStorer is a session storer implementation for saving sessions to a Redis database.

func NewDefaultRedisStorer

func NewDefaultRedisStorer(addr, password string, db int) (*RedisStorer, error)

NewDefaultRedisStorer takes a bind address of the Redis server host:port and returns a RedisStorer object with default values. The default values are: Addr: localhost:6379 Password: no password DB: First database (0) to be selected after connecting to Redis maxAge: 2 days (clear session stored in Redis after 2 days)

func NewRedisStorer

func NewRedisStorer(opts redis.Options, maxAge time.Duration) (*RedisStorer, error)

NewRedisStorer initializes and returns a new RedisStorer object. It takes a bind address of the Redis server host:port and the maxAge of how long each session should live in the Redis server. Persistent storage can be attained by setting maxAge to zero.

func (*RedisStorer) All

func (r *RedisStorer) All() ([]string, error)

All keys in the redis store

func (*RedisStorer) Del

func (r *RedisStorer) Del(key string) error

Del the session pointed to by the session id key and remove it.

func (*RedisStorer) Get

func (r *RedisStorer) Get(key string) (value string, err error)

Get returns the value string saved in the session pointed to by the session id key.

func (*RedisStorer) ResetExpiry

func (r *RedisStorer) ResetExpiry(key string) error

ResetExpiry resets the expiry of the key

func (*RedisStorer) Set

func (r *RedisStorer) Set(key, value string) error

Set saves the value string to the session pointed to by the session id key.

type Resetter

type Resetter interface {
	// ResetExpiry resets the age of the session to time.Now(), so that
	// MaxAge calculations are renewed
	ResetExpiry(w http.ResponseWriter, r *http.Request) error
	// ResetMiddleware will reset the users session expiry on every request
	ResetMiddleware(next http.Handler) http.Handler
	// MiddlewareWithReset converts the writer to a sessionsResponseWriter
	// and will reset the users session expiry on every request
	MiddlewareWithReset(next http.Handler) http.Handler
}

Resetter has reset functions

type StorageOverseer

type StorageOverseer struct {
	Storer Storer
	// contains filtered or unexported fields
}

StorageOverseer holds cookie related variables and a session storer

func NewStorageOverseer

func NewStorageOverseer(opts CookieOptions, storer Storer) *StorageOverseer

NewStorageOverseer returns a new storage overseer

func (*StorageOverseer) Del

Del deletes the session if it exists and sets the session cookie to expire instantly.

func (*StorageOverseer) Get

func (s *StorageOverseer) Get(w http.ResponseWriter, r *http.Request) (value string, err error)

Get looks in the cookie for the session ID and retrieves the value string stored in the session.

func (StorageOverseer) MiddlewareWithReset

func (m StorageOverseer) MiddlewareWithReset(next http.Handler) http.Handler

Middleware converts the ResponseWriter object to a sessionsResponseWriter for buffering cookies across session API requests. The sessionsResponseWriter implements cookieWriter.

MiddlewareWithReset also resets the users session expiry on each request. If you do not want this added functionality use Middleware instead.

func (*StorageOverseer) Regenerate

func (s *StorageOverseer) Regenerate(w http.ResponseWriter, r *http.Request) error

Regenerate a new session ID for your current session

func (*StorageOverseer) ResetExpiry

func (s *StorageOverseer) ResetExpiry(w http.ResponseWriter, r *http.Request) error

ResetExpiry resets the age of the session to time.Now(), so that MaxAge calculations are renewed

func (StorageOverseer) ResetMiddleware

func (m StorageOverseer) ResetMiddleware(next http.Handler) http.Handler

ResetMiddleware resets the users session expiry on each request.

Note: Generally you will want to use Middleware or MiddlewareWithReset instead of this middleware, but if you have a requirement to insert a middleware between the sessions Middleware and the sessions ResetMiddleware then you can use the Middleware first, and this one second, as a two-step process, instead of the combined MiddlewareWithReset middleware.

It's also important to note that the sessions Middleware must come BEFORE this middleware in the chain, or you will get a panic.

func (*StorageOverseer) SessionID

func (s *StorageOverseer) SessionID(w http.ResponseWriter, r *http.Request) (string, error)

SessionID returns the session ID stored in the cookie's value field. It will return a errNoSession error if no session exists.

func (*StorageOverseer) Set

Set looks in the cookie for the session ID and modifies the session with the new value. If the session does not exist it creates a new one.

type Storer

type Storer interface {
	// All returns all keys in the store
	All() (keys []string, err error)
	Get(key string) (value string, err error)
	Set(key, value string) error
	Del(key string) error
	ResetExpiry(key string) error
}

Storer provides methods to retrieve, add and delete sessions.

Jump to

Keyboard shortcuts

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