diff --git a/config.go b/config.go index 94e94a5f..f2c79634 100644 --- a/config.go +++ b/config.go @@ -83,14 +83,17 @@ type WebConfig struct { // SessionConfig holds session related config type SessionConfig struct { - SessionOn bool - SessionProvider string - SessionName string - SessionGCMaxLifetime int64 - SessionProviderConfig string - SessionCookieLifeTime int - SessionAutoSetCookie bool - SessionDomain string + SessionOn bool + SessionProvider string + SessionName string + SessionGCMaxLifetime int64 + SessionProviderConfig string + SessionCookieLifeTime int + SessionAutoSetCookie bool + SessionDomain string + EnableSidInHttpHeader bool // enable store/get the sessionId into/from http headers + SessionNameInHttpHeader string + EnableSidInUrlQuery bool // enable get the sessionId from Url Query params } // LogConfig holds Log related config @@ -183,14 +186,17 @@ func newBConfig() *Config { XSRFKey: "beegoxsrf", XSRFExpire: 0, Session: SessionConfig{ - SessionOn: false, - SessionProvider: "memory", - SessionName: "beegosessionID", - SessionGCMaxLifetime: 3600, - SessionProviderConfig: "", - SessionCookieLifeTime: 0, //set cookie default is the browser life - SessionAutoSetCookie: true, - SessionDomain: "", + SessionOn: false, + SessionProvider: "memory", + SessionName: "beegosessionID", + SessionGCMaxLifetime: 3600, + SessionProviderConfig: "", + SessionCookieLifeTime: 0, //set cookie default is the browser life + SessionAutoSetCookie: true, + SessionDomain: "", + EnableSidInHttpHeader: false, // enable store/get the sessionId into/from http headers + SessionNameInHttpHeader: "Beegosessionid", + EnableSidInUrlQuery: false, // enable get the sessionId from Url Query params }, }, Log: LogConfig{ diff --git a/hooks.go b/hooks.go index 610226b4..3dca1b8d 100644 --- a/hooks.go +++ b/hooks.go @@ -47,13 +47,16 @@ func registerSession() error { sessionConfig := AppConfig.String("sessionConfig") if sessionConfig == "" { conf := map[string]interface{}{ - "cookieName": BConfig.WebConfig.Session.SessionName, - "gclifetime": BConfig.WebConfig.Session.SessionGCMaxLifetime, - "providerConfig": filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig), - "secure": BConfig.Listen.EnableHTTPS, - "enableSetCookie": BConfig.WebConfig.Session.SessionAutoSetCookie, - "domain": BConfig.WebConfig.Session.SessionDomain, - "cookieLifeTime": BConfig.WebConfig.Session.SessionCookieLifeTime, + "cookieName": BConfig.WebConfig.Session.SessionName, + "gclifetime": BConfig.WebConfig.Session.SessionGCMaxLifetime, + "providerConfig": filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig), + "secure": BConfig.Listen.EnableHTTPS, + "enableSetCookie": BConfig.WebConfig.Session.SessionAutoSetCookie, + "domain": BConfig.WebConfig.Session.SessionDomain, + "cookieLifeTime": BConfig.WebConfig.Session.SessionCookieLifeTime, + "enableSidInHttpHeader": BConfig.WebConfig.Session.EnableSidInHttpHeader, + "sessionNameInHttpHeader": BConfig.WebConfig.Session.SessionNameInHttpHeader, + "enableSidInUrlQuery": BConfig.WebConfig.Session.EnableSidInUrlQuery, } confBytes, err := json.Marshal(conf) if err != nil { diff --git a/session/session.go b/session/session.go index 2c4b9351..53d89a27 100644 --- a/session/session.go +++ b/session/session.go @@ -31,10 +31,12 @@ import ( "crypto/rand" "encoding/hex" "encoding/json" + "errors" "fmt" "io" "log" "net/http" + "net/textproto" "net/url" "os" "time" @@ -81,15 +83,18 @@ func Register(name string, provide Provider) { } type managerConfig struct { - CookieName string `json:"cookieName"` - EnableSetCookie bool `json:"enableSetCookie,omitempty"` - Gclifetime int64 `json:"gclifetime"` - Maxlifetime int64 `json:"maxLifetime"` - Secure bool `json:"secure"` - CookieLifeTime int `json:"cookieLifeTime"` - ProviderConfig string `json:"providerConfig"` - Domain string `json:"domain"` - SessionIDLength int64 `json:"sessionIDLength"` + CookieName string `json:"cookieName"` + EnableSetCookie bool `json:"enableSetCookie,omitempty"` + Gclifetime int64 `json:"gclifetime"` + Maxlifetime int64 `json:"maxLifetime"` + Secure bool `json:"secure"` + CookieLifeTime int `json:"cookieLifeTime"` + ProviderConfig string `json:"providerConfig"` + Domain string `json:"domain"` + SessionIDLength int64 `json:"sessionIDLength"` + EnableSidInHttpHeader bool `json:"enableSidInHttpHeader"` + SessionNameInHttpHeader string `json:"sessionNameInHttpHeader"` + EnableSidInUrlQuery bool `json:"enableSidInUrlQuery"` } // Manager contains Provider and its configuration. @@ -124,6 +129,23 @@ func NewManager(provideName, config string) (*Manager, error) { if cf.Maxlifetime == 0 { cf.Maxlifetime = cf.Gclifetime } + + if cf.EnableSidInHttpHeader { + if cf.SessionNameInHttpHeader == "" { + err = errors.New("SessionNameInHttpHeader is empty") + panic(err) + return nil, err + } + + strMimeHeader := textproto.CanonicalMIMEHeaderKey(cf.SessionNameInHttpHeader) + if cf.SessionNameInHttpHeader != strMimeHeader { + strErrMsg := "SessionNameInHttpHeader (" + cf.SessionNameInHttpHeader + ") has the wrong format, it should be like this : " + strMimeHeader + err = errors.New(strErrMsg) + panic(err) + return nil, err + } + } + err = provider.SessionInit(cf.Maxlifetime, cf.ProviderConfig) if err != nil { return nil, err @@ -149,12 +171,24 @@ func NewManager(provideName, config string) (*Manager, error) { func (manager *Manager) getSid(r *http.Request) (string, error) { cookie, errs := r.Cookie(manager.config.CookieName) if errs != nil || cookie.Value == "" || cookie.MaxAge < 0 { - errs := r.ParseForm() - if errs != nil { - return "", errs + var sid string + if manager.config.EnableSidInUrlQuery { + errs := r.ParseForm() + if errs != nil { + return "", errs + } + + sid = r.FormValue(manager.config.CookieName) + } + + // if not found in Cookie / param, then read it from request headers + if manager.config.EnableSidInHttpHeader && sid == "" { + sids, isFound := r.Header[manager.config.SessionNameInHttpHeader] + if isFound && len(sids) != 0 { + return sids[0], nil + } } - sid := r.FormValue(manager.config.CookieName) return sid, nil } @@ -198,11 +232,21 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se } r.AddCookie(cookie) + if manager.config.EnableSidInHttpHeader { + r.Header.Set(manager.config.SessionNameInHttpHeader, sid) + w.Header().Set(manager.config.SessionNameInHttpHeader, sid) + } + return } // SessionDestroy Destroy session by its id in http request cookie. func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { + if manager.config.EnableSidInHttpHeader { + r.Header.Del(manager.config.SessionNameInHttpHeader) + w.Header().Del(manager.config.SessionNameInHttpHeader) + } + cookie, err := r.Cookie(manager.config.CookieName) if err != nil || cookie.Value == "" { return @@ -267,6 +311,12 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque http.SetCookie(w, cookie) } r.AddCookie(cookie) + + if manager.config.EnableSidInHttpHeader { + r.Header.Set(manager.config.SessionNameInHttpHeader, sid) + w.Header().Set(manager.config.SessionNameInHttpHeader, sid) + } + return }