mirror of
https://github.com/rls-moe/nyx
synced 2024-11-14 22:12:24 +00:00
124 lines
3.5 KiB
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()
|
|
}
|