nyx/vendor/github.com/icza/session/cookie_manager.go

124 lines
3.5 KiB
Go

/*
A secure, cookie based session Manager implementation.
*/
package session
import (
"net/http"
"time"
)
// CookieManager is a secure, cookie based session Manager implementation.
// Only the session ID is transmitted / stored at the clients, and it is managed using cookies.
type CookieManager struct {
store Store // Backing Store
sessIDCookieName string // Name of the cookie used for storing the session id
cookieSecure bool // Tells if session ID cookies are to be sent only over HTTPS
cookieMaxAgeSec int // Max age for session ID cookies in seconds
cookiePath string // Cookie path to use
}
// CookieMngrOptions defines options that may be passed when creating a new CookieManager.
// All fields are optional; default value will be used for any field that has the zero value.
type CookieMngrOptions struct {
// Name of the cookie used for storing the session id; default value is "sessid"
SessIDCookieName string
// Tells if session ID cookies are allowed to be sent over unsecure HTTP too (else only HTTPS);
// default value is false (only HTTPS)
AllowHTTP bool
// Max age for session ID cookies; default value is 30 days
CookieMaxAge time.Duration
// Cookie path to use; default value is the root: "/"
CookiePath string
}
// Pointer to zero value of CookieMngrOptions to be reused for efficiency.
var zeroCookieMngrOptions = new(CookieMngrOptions)
// NewCookieManager creates a new, cookie based session Manager with default options.
// Default values of options are listed in the CookieMngrOptions type.
func NewCookieManager(store Store) Manager {
return NewCookieManagerOptions(store, zeroCookieMngrOptions)
}
// NewCookieManagerOptions creates a new, cookie based session Manager with the specified options.
func NewCookieManagerOptions(store Store, o *CookieMngrOptions) Manager {
m := &CookieManager{
store: store,
cookieSecure: !o.AllowHTTP,
sessIDCookieName: o.SessIDCookieName,
cookiePath: o.CookiePath,
}
if m.sessIDCookieName == "" {
m.sessIDCookieName = "sessid"
}
if o.CookieMaxAge == 0 {
m.cookieMaxAgeSec = 30 * 24 * 60 * 60 // 30 days max age
} else {
m.cookieMaxAgeSec = int(o.CookieMaxAge.Seconds())
}
if m.cookiePath == "" {
m.cookiePath = "/"
}
return m
}
// Get is to implement Manager.Get().
func (m *CookieManager) Get(r *http.Request) Session {
c, err := r.Cookie(m.sessIDCookieName)
if err != nil {
return nil
}
return m.store.Get(c.Value)
}
// Add is to implement Manager.Add().
func (m *CookieManager) Add(sess Session, w http.ResponseWriter) {
// HttpOnly: do not allow non-HTTP access to it (like javascript) to prevent stealing it...
// Secure: only send it over HTTPS
// MaxAge: to specify the max age of the cookie in seconds, else it's a session cookie and gets deleted after the browser is closed.
c := http.Cookie{
Name: m.sessIDCookieName,
Value: sess.ID(),
Path: m.cookiePath,
HttpOnly: true,
Secure: m.cookieSecure,
MaxAge: m.cookieMaxAgeSec,
}
http.SetCookie(w, &c)
m.store.Add(sess)
}
// Remove is to implement Manager.Remove().
func (m *CookieManager) Remove(sess Session, w http.ResponseWriter) {
// Set the cookie with empty value and 0 max age
c := http.Cookie{
Name: m.sessIDCookieName,
Value: "",
Path: m.cookiePath,
HttpOnly: true,
Secure: m.cookieSecure,
MaxAge: -1, // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
}
http.SetCookie(w, &c)
m.store.Remove(sess)
}
// Close is to implement Manager.Close().
func (m *CookieManager) Close() {
m.store.Close()
}