mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Updated session lib
This commit is contained in:
parent
e9fcca16bd
commit
aafe2c5b98
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -30,7 +30,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/macaron-contrib/session",
|
||||
"Rev": "f00d48fd4f85088603c1493b0a99fdfe95d0658c"
|
||||
"Rev": "65b8817c40cb5bdce08673a15fd2a648c2ba0e16"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/go-sqlite3",
|
||||
|
171
Godeps/_workspace/src/github.com/macaron-contrib/session/README.md
generated
vendored
171
Godeps/_workspace/src/github.com/macaron-contrib/session/README.md
generated
vendored
@ -1,177 +1,16 @@
|
||||
session
|
||||
session [](https://drone.io/github.com/macaron-contrib/session/latest) [](http://gocover.io/github.com/macaron-contrib/session)
|
||||
=======
|
||||
|
||||
Middleware session is the session manager of [Macaron](https://github.com/Unknwon/macaron). It can use many session providers, including cookie, memory, file, redis, memcache, PostgreSQL, MySQL, and couchbase.
|
||||
|
||||
[API Reference](https://gowalker.org/github.com/macaron-contrib/session)
|
||||
Middleware session provides session management for [Macaron](https://github.com/Unknwon/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase and Ledis.
|
||||
|
||||
### Installation
|
||||
|
||||
go get github.com/macaron-contrib/session
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := macaron.Classic()
|
||||
m.Use(session.Sessioner())
|
||||
|
||||
m.Get("/", func(sess session.Store) string {
|
||||
sess.Set("session", "session middleware")
|
||||
return sess.Get("session").(string)
|
||||
})
|
||||
|
||||
m.Get("/signup", func(ctx *macaron.Context, f *session.Flash) {
|
||||
f.Success("yes!!!")
|
||||
f.Error("opps...")
|
||||
// Use following fields in template
|
||||
// - {{.Flash.SuccessMsg}}
|
||||
// - {{.Flash.ErrorMsg}}
|
||||
ctx.HTML(200, "signup", ctx.Data)
|
||||
})
|
||||
|
||||
m.Run()
|
||||
}
|
||||
```
|
||||
|
||||
To use redis, memcache, PostgreSQL, MySQL, or couchbase as adapter, you should import their init functions:
|
||||
|
||||
```go
|
||||
import (
|
||||
_ "github.com/macaron-contrib/session/redis"
|
||||
_ "github.com/macaron-contrib/session/memcache"
|
||||
_ "github.com/macaron-contrib/session/postgres"
|
||||
_ "github.com/macaron-contrib/session/mysql"
|
||||
_ "github.com/macaron-contrib/session/couchbase"
|
||||
)
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
`session.Sessioner` comes with a variety of configuration options:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "memory", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "./tmp", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
### Example Options
|
||||
|
||||
- memory:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "memory", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "./tmp", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
- file:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "file", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "./tmp", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
- Redis:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "redis", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "127.0.0.1:6379,100,macaron", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
- MySQL:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "mysql", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "username:password@protocol(address)/dbname?param=value", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
- Cookie:
|
||||
|
||||
```go
|
||||
// ...
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: "cookie", // Name of provider.
|
||||
Config: Config{
|
||||
CookieName: "MacaronSession", // Key name store in cookie.
|
||||
Gclifetime: 3600, // GC interval for memory adapter.
|
||||
ProviderConfig: "{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}", // Provider configuration string.
|
||||
},
|
||||
}))
|
||||
// ...
|
||||
```
|
||||
|
||||
## How to write own provider?
|
||||
|
||||
When you develop a web app, maybe you want to write own provider because you must meet the requirements.
|
||||
|
||||
Writing a provider is easy. You only need to define two struct types
|
||||
(Session and Provider), which satisfy the interface definition.
|
||||
Maybe you will find the **memory** provider is a good example.
|
||||
|
||||
type Store interface {
|
||||
Set(key, value interface{}) error //set session value
|
||||
Get(key interface{}) interface{} //get session value
|
||||
Delete(key interface{}) error //delete session value
|
||||
SessionID() string //back current sessionID
|
||||
SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data
|
||||
Flush() error //delete all data
|
||||
}
|
||||
|
||||
type Provider interface {
|
||||
SessionInit(gclifetime int64, config string) error
|
||||
SessionRead(sid string) (SessionStore, error)
|
||||
SessionExist(sid string) bool
|
||||
SessionRegenerate(oldsid, sid string) (Store, error)
|
||||
SessionDestroy(sid string) error
|
||||
SessionAll() int //get all active session
|
||||
SessionGC()
|
||||
}
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/github.com/macaron-contrib/session)
|
||||
- [Documentation](http://macaron.gogs.io/docs/middlewares/session)
|
||||
|
||||
## License
|
||||
|
||||
|
191
Godeps/_workspace/src/github.com/macaron-contrib/session/couchbase/couchbase.go
generated
vendored
191
Godeps/_workspace/src/github.com/macaron-contrib/session/couchbase/couchbase.go
generated
vendored
@ -16,7 +16,6 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -25,72 +24,78 @@ import (
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
var couchbpder = &CouchbaseProvider{}
|
||||
|
||||
// CouchbaseSessionStore represents a couchbase session store implementation.
|
||||
type CouchbaseSessionStore struct {
|
||||
b *couchbase.Bucket
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
data map[interface{}]interface{}
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *CouchbaseSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *CouchbaseSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *CouchbaseSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *CouchbaseSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *CouchbaseSessionStore) Release() error {
|
||||
defer s.b.Close()
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.b.Set(s.sid, int(s.maxlifetime), data)
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *CouchbaseSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// CouchbaseProvider represents a couchbase session provider implementation.
|
||||
type CouchbaseProvider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
connStr string
|
||||
pool string
|
||||
bucket string
|
||||
b *couchbase.Bucket
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) Set(key, value interface{}) error {
|
||||
cs.lock.Lock()
|
||||
defer cs.lock.Unlock()
|
||||
cs.values[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) Get(key interface{}) interface{} {
|
||||
cs.lock.RLock()
|
||||
defer cs.lock.RUnlock()
|
||||
if v, ok := cs.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) Delete(key interface{}) error {
|
||||
cs.lock.Lock()
|
||||
defer cs.lock.Unlock()
|
||||
delete(cs.values, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) Flush() error {
|
||||
cs.lock.Lock()
|
||||
defer cs.lock.Unlock()
|
||||
cs.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) SessionID() string {
|
||||
return cs.sid
|
||||
}
|
||||
|
||||
func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
defer cs.b.Close()
|
||||
|
||||
bo, err := session.EncodeGob(cs.values)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cs.b.Set(cs.sid, int(cs.maxlifetime), bo)
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
|
||||
c, err := couchbase.Connect(cp.savePath)
|
||||
c, err := couchbase.Connect(cp.connStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@ -108,32 +113,32 @@ func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
|
||||
return bucket
|
||||
}
|
||||
|
||||
// init couchbase session
|
||||
// savepath like couchbase server REST/JSON URL
|
||||
// Init initializes memory session provider.
|
||||
// connStr is couchbase server REST/JSON URL
|
||||
// e.g. http://host:port/, Pool, Bucket
|
||||
func (cp *CouchbaseProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
cp.maxlifetime = maxlifetime
|
||||
configs := strings.Split(savePath, ",")
|
||||
func (p *CouchbaseProvider) Init(maxlifetime int64, connStr string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
configs := strings.Split(connStr, ",")
|
||||
if len(configs) > 0 {
|
||||
cp.savePath = configs[0]
|
||||
p.connStr = configs[0]
|
||||
}
|
||||
if len(configs) > 1 {
|
||||
cp.pool = configs[1]
|
||||
p.pool = configs[1]
|
||||
}
|
||||
if len(configs) > 2 {
|
||||
cp.bucket = configs[2]
|
||||
p.bucket = configs[2]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// read couchbase session by sid
|
||||
func (cp *CouchbaseProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
cp.b = cp.getBucket()
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *CouchbaseProvider) Read(sid string) (session.RawStore, error) {
|
||||
p.b = p.getBucket()
|
||||
|
||||
var doc []byte
|
||||
|
||||
err := cp.b.Get(sid, &doc)
|
||||
err := p.b.Get(sid, &doc)
|
||||
var kv map[interface{}]interface{}
|
||||
if doc == nil {
|
||||
kv = make(map[interface{}]interface{})
|
||||
@ -144,38 +149,49 @@ func (cp *CouchbaseProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
}
|
||||
}
|
||||
|
||||
cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
|
||||
cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) SessionExist(sid string) bool {
|
||||
cp.b = cp.getBucket()
|
||||
defer cp.b.Close()
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *CouchbaseProvider) Exist(sid string) bool {
|
||||
p.b = p.getBucket()
|
||||
defer p.b.Close()
|
||||
|
||||
var doc []byte
|
||||
|
||||
if err := cp.b.Get(sid, &doc); err != nil || doc == nil {
|
||||
if err := p.b.Get(sid, &doc); err != nil || doc == nil {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
cp.b = cp.getBucket()
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *CouchbaseProvider) Destory(sid string) error {
|
||||
p.b = p.getBucket()
|
||||
defer p.b.Close()
|
||||
|
||||
p.b.Delete(sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *CouchbaseProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
p.b = p.getBucket()
|
||||
|
||||
var doc []byte
|
||||
if err := cp.b.Get(oldsid, &doc); err != nil || doc == nil {
|
||||
cp.b.Set(sid, int(cp.maxlifetime), "")
|
||||
if err := p.b.Get(oldsid, &doc); err != nil || doc == nil {
|
||||
p.b.Set(sid, int(p.maxlifetime), "")
|
||||
} else {
|
||||
err := cp.b.Delete(oldsid)
|
||||
err := p.b.Delete(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _ = cp.b.Add(sid, int(cp.maxlifetime), doc)
|
||||
_, _ = p.b.Add(sid, int(p.maxlifetime), doc)
|
||||
}
|
||||
|
||||
err := cp.b.Get(sid, &doc)
|
||||
err := p.b.Get(sid, &doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -189,26 +205,19 @@ func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (session.RawS
|
||||
}
|
||||
}
|
||||
|
||||
cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
|
||||
cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) SessionDestroy(sid string) error {
|
||||
cp.b = cp.getBucket()
|
||||
defer cp.b.Close()
|
||||
|
||||
cp.b.Delete(sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) SessionGC() {
|
||||
return
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) SessionAll() int {
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *CouchbaseProvider) Count() int {
|
||||
// FIXME
|
||||
return 0
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *CouchbaseProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("couchbase", couchbpder)
|
||||
session.Register("couchbase", &CouchbaseProvider{})
|
||||
}
|
||||
|
145
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.go
generated
vendored
145
Godeps/_workspace/src/github.com/macaron-contrib/session/ledis/ledis.go
generated
vendored
@ -16,89 +16,89 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/astaxie/beego/session"
|
||||
"github.com/siddontang/ledisdb/config"
|
||||
"github.com/siddontang/ledisdb/ledis"
|
||||
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
var ledispder = &LedisProvider{}
|
||||
var c *ledis.DB
|
||||
|
||||
// ledis session store
|
||||
// LedisSessionStore represents a ledis session store implementation.
|
||||
type LedisSessionStore struct {
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
data map[interface{}]interface{}
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// set value in ledis session
|
||||
func (ls *LedisSessionStore) Set(key, value interface{}) error {
|
||||
ls.lock.Lock()
|
||||
defer ls.lock.Unlock()
|
||||
ls.values[key] = value
|
||||
// Set sets value to given key in session.
|
||||
func (s *LedisSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value in ledis session
|
||||
func (ls *LedisSessionStore) Get(key interface{}) interface{} {
|
||||
ls.lock.RLock()
|
||||
defer ls.lock.RUnlock()
|
||||
if v, ok := ls.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// Get gets value by given key in session.
|
||||
func (s *LedisSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// delete value in ledis session
|
||||
func (ls *LedisSessionStore) Delete(key interface{}) error {
|
||||
ls.lock.Lock()
|
||||
defer ls.lock.Unlock()
|
||||
delete(ls.values, key)
|
||||
// Delete delete a key from session.
|
||||
func (s *LedisSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in ledis session
|
||||
func (ls *LedisSessionStore) Flush() error {
|
||||
ls.lock.Lock()
|
||||
defer ls.lock.Unlock()
|
||||
ls.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
// ID returns current session ID.
|
||||
func (s *LedisSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// get ledis session id
|
||||
func (ls *LedisSessionStore) SessionID() string {
|
||||
return ls.sid
|
||||
}
|
||||
|
||||
// save session values to ledis
|
||||
func (ls *LedisSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
b, err := session.EncodeGob(ls.values)
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *LedisSessionStore) Release() error {
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
c.Set([]byte(ls.sid), b)
|
||||
c.Expire([]byte(ls.sid), ls.maxlifetime)
|
||||
if err = c.Set([]byte(s.sid), data); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.Expire([]byte(s.sid), s.maxlifetime)
|
||||
return err
|
||||
}
|
||||
|
||||
// ledis session provider
|
||||
// Flush deletes all session data.
|
||||
func (s *LedisSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// LedisProvider represents a ledis session provider implementation.
|
||||
type LedisProvider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
}
|
||||
|
||||
// init ledis session
|
||||
// savepath like ledis server saveDataPath,pool size
|
||||
// e.g. 127.0.0.1:6379,100,astaxie
|
||||
func (lp *LedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
lp.maxlifetime = maxlifetime
|
||||
lp.savePath = savePath
|
||||
// Init initializes memory session provider.
|
||||
func (p *LedisProvider) Init(maxlifetime int64, savePath string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
p.savePath = savePath
|
||||
cfg := new(config.Config)
|
||||
cfg.DataDir = lp.savePath
|
||||
cfg.DataDir = p.savePath
|
||||
var err error
|
||||
nowLedis, err := ledis.Open(cfg)
|
||||
c, err = nowLedis.Select(0)
|
||||
@ -109,8 +109,8 @@ func (lp *LedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// read ledis session by sid
|
||||
func (lp *LedisProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *LedisProvider) Read(sid string) (session.RawStore, error) {
|
||||
kvs, err := c.Get([]byte(sid))
|
||||
var kv map[interface{}]interface{}
|
||||
if len(kvs) == 0 {
|
||||
@ -121,12 +121,12 @@ func (lp *LedisProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ls := &LedisSessionStore{sid: sid, values: kv, maxlifetime: lp.maxlifetime}
|
||||
ls := &LedisSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return ls, nil
|
||||
}
|
||||
|
||||
// check ledis session exist by sid
|
||||
func (lp *LedisProvider) SessionExist(sid string) bool {
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *LedisProvider) Exist(sid string) bool {
|
||||
count, _ := c.Exists([]byte(sid))
|
||||
if count == 0 {
|
||||
return false
|
||||
@ -135,19 +135,25 @@ func (lp *LedisProvider) SessionExist(sid string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for ledis session
|
||||
func (lp *LedisProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *LedisProvider) Destory(sid string) error {
|
||||
_, err := c.Del([]byte(sid))
|
||||
return err
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *LedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
count, _ := c.Exists([]byte(sid))
|
||||
if count == 0 {
|
||||
// oldsid doesn't exists, set the new sid directly
|
||||
// ignore error here, since if it return error
|
||||
// the existed value will be 0
|
||||
c.Set([]byte(sid), []byte(""))
|
||||
c.Expire([]byte(sid), lp.maxlifetime)
|
||||
c.Expire([]byte(sid), p.maxlifetime)
|
||||
} else {
|
||||
data, _ := c.Get([]byte(oldsid))
|
||||
c.Set([]byte(sid), data)
|
||||
c.Expire([]byte(sid), lp.maxlifetime)
|
||||
c.Expire([]byte(sid), p.maxlifetime)
|
||||
}
|
||||
kvs, err := c.Get([]byte(sid))
|
||||
var kv map[interface{}]interface{}
|
||||
@ -159,26 +165,19 @@ func (lp *LedisProvider) SessionRegenerate(oldsid, sid string) (session.SessionS
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ls := &LedisSessionStore{sid: sid, values: kv, maxlifetime: lp.maxlifetime}
|
||||
ls := &LedisSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return ls, nil
|
||||
}
|
||||
|
||||
// delete ledis session by id
|
||||
func (lp *LedisProvider) SessionDestroy(sid string) error {
|
||||
c.Del([]byte(sid))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Impelment method, no used.
|
||||
func (lp *LedisProvider) SessionGC() {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo
|
||||
func (lp *LedisProvider) SessionAll() int {
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *LedisProvider) Count() int {
|
||||
// FIXME
|
||||
return 0
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *LedisProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("ledis", ledispder)
|
||||
session.Register("ledis", &LedisProvider{})
|
||||
}
|
||||
|
165
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.go
generated
vendored
165
Godeps/_workspace/src/github.com/macaron-contrib/session/memcache/memcache.go
generated
vendored
@ -16,7 +16,6 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -26,73 +25,72 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
mempder = &MemProvider{}
|
||||
client *memcache.Client
|
||||
client *memcache.Client
|
||||
)
|
||||
|
||||
// memcache session store
|
||||
// MemcacheSessionStore represents a memcache session store implementation.
|
||||
type MemcacheSessionStore struct {
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
data map[interface{}]interface{}
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// set value in memcache session
|
||||
func (rs *MemcacheSessionStore) Set(key, value interface{}) error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
rs.values[key] = value
|
||||
// Set sets value to given key in session.
|
||||
func (s *MemcacheSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value in memcache session
|
||||
func (rs *MemcacheSessionStore) Get(key interface{}) interface{} {
|
||||
rs.lock.RLock()
|
||||
defer rs.lock.RUnlock()
|
||||
if v, ok := rs.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// Get gets value by given key in session.
|
||||
func (s *MemcacheSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// delete value in memcache session
|
||||
func (rs *MemcacheSessionStore) Delete(key interface{}) error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
delete(rs.values, key)
|
||||
// Delete delete a key from session.
|
||||
func (s *MemcacheSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in memcache session
|
||||
func (rs *MemcacheSessionStore) Flush() error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
rs.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
// ID returns current session ID.
|
||||
func (s *MemcacheSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// get redis session id
|
||||
func (rs *MemcacheSessionStore) SessionID() string {
|
||||
return rs.sid
|
||||
}
|
||||
|
||||
// save session values to redis
|
||||
func (rs *MemcacheSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
b, err := session.EncodeGob(rs.values)
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *MemcacheSessionStore) Release() error {
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
client.Set(&memcache.Item{
|
||||
Key: rs.sid,
|
||||
Value: b,
|
||||
Expiration: int32(rs.maxlifetime),
|
||||
return client.Set(&memcache.Item{
|
||||
Key: s.sid,
|
||||
Value: data,
|
||||
Expiration: int32(s.maxlifetime),
|
||||
})
|
||||
}
|
||||
|
||||
// redis session provider
|
||||
// Flush deletes all session data.
|
||||
func (s *MemcacheSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// MemProvider represents a memcache session provider implementation.
|
||||
type MemProvider struct {
|
||||
maxlifetime int64
|
||||
conninfo []string
|
||||
@ -100,25 +98,25 @@ type MemProvider struct {
|
||||
password string
|
||||
}
|
||||
|
||||
// init redis session
|
||||
// savepath like
|
||||
// Init initializes memory session provider.
|
||||
// connStrs can be multiple connection strings separate by ;
|
||||
// e.g. 127.0.0.1:9090
|
||||
func (rp *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
rp.maxlifetime = maxlifetime
|
||||
rp.conninfo = strings.Split(savePath, ";")
|
||||
client = memcache.New(rp.conninfo...)
|
||||
func (p *MemProvider) Init(maxlifetime int64, connStrs string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
p.conninfo = strings.Split(connStrs, ";")
|
||||
client = memcache.New(p.conninfo...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rp *MemProvider) connectInit() error {
|
||||
client = memcache.New(rp.conninfo...)
|
||||
func (p *MemProvider) connectInit() error {
|
||||
client = memcache.New(p.conninfo...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// read redis session by sid
|
||||
func (rp *MemProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *MemProvider) Read(sid string) (session.RawStore, error) {
|
||||
if client == nil {
|
||||
if err := rp.connectInit(); err != nil {
|
||||
if err := p.connectInit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -138,14 +136,14 @@ func (rp *MemProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
}
|
||||
}
|
||||
|
||||
rs := &MemcacheSessionStore{sid: sid, values: kv, maxlifetime: rp.maxlifetime}
|
||||
rs := &MemcacheSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// check redis session exist by sid
|
||||
func (rp *MemProvider) SessionExist(sid string) bool {
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *MemProvider) Exist(sid string) bool {
|
||||
if client == nil {
|
||||
if err := rp.connectInit(); err != nil {
|
||||
if err := p.connectInit(); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -157,10 +155,21 @@ func (rp *MemProvider) SessionExist(sid string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for redis session
|
||||
func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *MemProvider) Destory(sid string) error {
|
||||
if client == nil {
|
||||
if err := rp.connectInit(); err != nil {
|
||||
if err := p.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return client.Delete(sid)
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
if client == nil {
|
||||
if err := p.connectInit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -172,13 +181,13 @@ func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.RawStore,
|
||||
// the existed value will be 0
|
||||
item.Key = sid
|
||||
item.Value = []byte("")
|
||||
item.Expiration = int32(rp.maxlifetime)
|
||||
item.Expiration = int32(p.maxlifetime)
|
||||
client.Set(item)
|
||||
} else {
|
||||
client.Delete(oldsid)
|
||||
item.Key = sid
|
||||
item.Value = item.Value
|
||||
item.Expiration = int32(rp.maxlifetime)
|
||||
item.Expiration = int32(p.maxlifetime)
|
||||
client.Set(item)
|
||||
contain = item.Value
|
||||
}
|
||||
@ -194,31 +203,19 @@ func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.RawStore,
|
||||
}
|
||||
}
|
||||
|
||||
rs := &MemcacheSessionStore{sid: sid, values: kv, maxlifetime: rp.maxlifetime}
|
||||
rs := &MemcacheSessionStore{sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// delete redis session by id
|
||||
func (rp *MemProvider) SessionDestroy(sid string) error {
|
||||
if client == nil {
|
||||
if err := rp.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return client.Delete(sid)
|
||||
}
|
||||
|
||||
// Impelment method, no used.
|
||||
func (rp *MemProvider) SessionGC() {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo
|
||||
func (rp *MemProvider) SessionAll() int {
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *MemProvider) Count() int {
|
||||
// FIXME
|
||||
return 0
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *MemProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("memcache", mempder)
|
||||
session.Register("memcache", &MemProvider{})
|
||||
}
|
||||
|
183
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.go
generated
vendored
183
Godeps/_workspace/src/github.com/macaron-contrib/session/mysql/mysql.go
generated
vendored
@ -15,17 +15,8 @@
|
||||
|
||||
package session
|
||||
|
||||
// mysql session support need create table as sql:
|
||||
// CREATE TABLE `session` (
|
||||
// `session_key` char(64) NOT NULL,
|
||||
// session_data` blob,
|
||||
// `session_expiry` int(11) unsigned NOT NULL,
|
||||
// PRIMARY KEY (`session_key`)
|
||||
// ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -34,96 +25,90 @@ import (
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
var mysqlpder = &MysqlProvider{}
|
||||
|
||||
// mysql session store
|
||||
// MysqlSessionStore represents a mysql session store implementation.
|
||||
type MysqlSessionStore struct {
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// set value in mysql session.
|
||||
// it is temp value in map.
|
||||
func (st *MysqlSessionStore) Set(key, value interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values[key] = value
|
||||
// Set sets value to given key in session.
|
||||
func (s *MysqlSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value from mysql session
|
||||
func (st *MysqlSessionStore) Get(key interface{}) interface{} {
|
||||
st.lock.RLock()
|
||||
defer st.lock.RUnlock()
|
||||
if v, ok := st.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// Get gets value by given key in session.
|
||||
func (s *MysqlSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// delete value in mysql session
|
||||
func (st *MysqlSessionStore) Delete(key interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
delete(st.values, key)
|
||||
// Delete delete a key from session.
|
||||
func (s *MysqlSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in mysql session
|
||||
func (st *MysqlSessionStore) Flush() error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
// ID returns current session ID.
|
||||
func (s *MysqlSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// get session id of this mysql session store
|
||||
func (st *MysqlSessionStore) SessionID() string {
|
||||
return st.sid
|
||||
}
|
||||
|
||||
// save mysql session values to database.
|
||||
// must call this method to save values to database.
|
||||
func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
defer st.c.Close()
|
||||
b, err := session.EncodeGob(st.values)
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *MysqlSessionStore) Release() error {
|
||||
defer s.c.Close()
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
st.c.Exec("UPDATE session set `session_data`=?, `session_expiry`=? where session_key=?",
|
||||
b, time.Now().Unix(), st.sid)
|
||||
|
||||
_, err = s.c.Exec("UPDATE session set `session_data`=?, `session_expiry`=? where session_key=?",
|
||||
data, time.Now().Unix(), s.sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// mysql session provider
|
||||
// Flush deletes all session data.
|
||||
func (s *MysqlSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// MysqlProvider represents a mysql session provider implementation.
|
||||
type MysqlProvider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
connStr string
|
||||
}
|
||||
|
||||
// connect to mysql
|
||||
func (mp *MysqlProvider) connectInit() *sql.DB {
|
||||
db, e := sql.Open("mysql", mp.savePath)
|
||||
func (p *MysqlProvider) connectInit() *sql.DB {
|
||||
db, e := sql.Open("mysql", p.connStr)
|
||||
if e != nil {
|
||||
return nil
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// init mysql session.
|
||||
// savepath is the connection string of mysql.
|
||||
func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
mp.maxlifetime = maxlifetime
|
||||
mp.savePath = savePath
|
||||
// Init initializes memory session provider.
|
||||
func (p *MysqlProvider) Init(maxlifetime int64, connStr string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
p.connStr = connStr
|
||||
return nil
|
||||
}
|
||||
|
||||
// get mysql session by sid
|
||||
func (mp *MysqlProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
c := mp.connectInit()
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *MysqlProvider) Read(sid string) (session.RawStore, error) {
|
||||
c := p.connectInit()
|
||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
||||
var sessiondata []byte
|
||||
err := row.Scan(&sessiondata)
|
||||
@ -140,14 +125,15 @@ func (mp *MysqlProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rs := &MysqlSessionStore{c: c, sid: sid, values: kv}
|
||||
rs := &MysqlSessionStore{c: c, sid: sid, data: kv}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// check mysql session exist
|
||||
func (mp *MysqlProvider) SessionExist(sid string) bool {
|
||||
c := mp.connectInit()
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *MysqlProvider) Exist(sid string) bool {
|
||||
c := p.connectInit()
|
||||
defer c.Close()
|
||||
|
||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
||||
var sessiondata []byte
|
||||
err := row.Scan(&sessiondata)
|
||||
@ -158,9 +144,18 @@ func (mp *MysqlProvider) SessionExist(sid string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for mysql session
|
||||
func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := mp.connectInit()
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *MysqlProvider) Destory(sid string) (err error) {
|
||||
c := p.connectInit()
|
||||
if _, err = c.Exec("DELETE FROM session where session_key=?", sid); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *MysqlProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := p.connectInit()
|
||||
row := c.QueryRow("select session_data from session where session_key=?", oldsid)
|
||||
var sessiondata []byte
|
||||
err := row.Scan(&sessiondata)
|
||||
@ -177,30 +172,15 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.RawStore
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rs := &MysqlSessionStore{c: c, sid: sid, values: kv}
|
||||
rs := &MysqlSessionStore{c: c, sid: sid, data: kv}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// delete mysql session by sid
|
||||
func (mp *MysqlProvider) SessionDestroy(sid string) error {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE FROM session where session_key=?", sid)
|
||||
c.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// delete expired values in mysql session
|
||||
func (mp *MysqlProvider) SessionGC() {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// count values in mysql session
|
||||
func (mp *MysqlProvider) SessionAll() int {
|
||||
c := mp.connectInit()
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *MysqlProvider) Count() int {
|
||||
c := p.connectInit()
|
||||
defer c.Close()
|
||||
|
||||
var total int
|
||||
err := c.QueryRow("SELECT count(*) as num from session").Scan(&total)
|
||||
if err != nil {
|
||||
@ -209,6 +189,13 @@ func (mp *MysqlProvider) SessionAll() int {
|
||||
return total
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("mysql", mysqlpder)
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (mp *MysqlProvider) GC() {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
|
||||
c.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("mysql", &MysqlProvider{})
|
||||
}
|
||||
|
203
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgresql.go
generated
vendored
203
Godeps/_workspace/src/github.com/macaron-contrib/session/postgres/postgresql.go
generated
vendored
@ -15,38 +15,8 @@
|
||||
|
||||
package session
|
||||
|
||||
/*
|
||||
|
||||
beego session provider for postgresql
|
||||
-------------------------------------
|
||||
|
||||
depends on github.com/lib/pq:
|
||||
|
||||
go install github.com/lib/pq
|
||||
|
||||
|
||||
needs this table in your database:
|
||||
|
||||
CREATE TABLE session (
|
||||
session_key char(64) NOT NULL,
|
||||
session_data bytea,
|
||||
session_expiry timestamp NOT NULL,
|
||||
CONSTRAINT session_key PRIMARY KEY(session_key)
|
||||
);
|
||||
|
||||
|
||||
will be activated with these settings in app.conf:
|
||||
|
||||
SessionOn = true
|
||||
SessionProvider = postgresql
|
||||
SessionSavePath = "user=a password=b dbname=c sslmode=disable"
|
||||
SessionName = session
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -55,96 +25,93 @@ import (
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
var postgresqlpder = &PostgresqlProvider{}
|
||||
|
||||
// postgresql session store
|
||||
// PostgresqlSessionStore represents a postgresql session store implementation.
|
||||
type PostgresqlSessionStore struct {
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// set value in postgresql session.
|
||||
// it is temp value in map.
|
||||
func (st *PostgresqlSessionStore) Set(key, value interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values[key] = value
|
||||
// Set sets value to given key in session.
|
||||
func (s *PostgresqlSessionStore) Set(key, value interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value from postgresql session
|
||||
func (st *PostgresqlSessionStore) Get(key interface{}) interface{} {
|
||||
st.lock.RLock()
|
||||
defer st.lock.RUnlock()
|
||||
if v, ok := st.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// Get gets value by given key in session.
|
||||
func (s *PostgresqlSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// delete value in postgresql session
|
||||
func (st *PostgresqlSessionStore) Delete(key interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
delete(st.values, key)
|
||||
// Delete delete a key from session.
|
||||
func (s *PostgresqlSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in postgresql session
|
||||
func (st *PostgresqlSessionStore) Flush() error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// get session id of this postgresql session store
|
||||
func (st *PostgresqlSessionStore) SessionID() string {
|
||||
return st.sid
|
||||
// ID returns current session ID.
|
||||
func (s *PostgresqlSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// save postgresql session values to database.
|
||||
// must call this method to save values to database.
|
||||
func (st *PostgresqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
defer st.c.Close()
|
||||
b, err := session.EncodeGob(st.values)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
st.c.Exec("UPDATE session set session_data=$1, session_expiry=$2 where session_key=$3",
|
||||
b, time.Now().Format(time.RFC3339), st.sid)
|
||||
func (s *PostgresqlSessionStore) Release() error {
|
||||
defer s.c.Close()
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.c.Exec("UPDATE session set session_data=$1, session_expiry=$2 where session_key=$3",
|
||||
data, time.Now().Format(time.RFC3339), s.sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// postgresql session provider
|
||||
// Flush deletes all session data.
|
||||
func (s *PostgresqlSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// PostgresqlProvider represents a postgresql session provider implementation.
|
||||
type PostgresqlProvider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
connStr string
|
||||
}
|
||||
|
||||
// connect to postgresql
|
||||
func (mp *PostgresqlProvider) connectInit() *sql.DB {
|
||||
db, e := sql.Open("postgres", mp.savePath)
|
||||
func (p *PostgresqlProvider) connectInit() *sql.DB {
|
||||
db, e := sql.Open("postgres", p.connStr)
|
||||
if e != nil {
|
||||
return nil
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// init postgresql session.
|
||||
// savepath is the connection string of postgresql.
|
||||
func (mp *PostgresqlProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
mp.maxlifetime = maxlifetime
|
||||
mp.savePath = savePath
|
||||
// Init initializes memory session provider.
|
||||
func (p *PostgresqlProvider) Init(maxlifetime int64, connStr string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
p.connStr = connStr
|
||||
return nil
|
||||
}
|
||||
|
||||
// get postgresql session by sid
|
||||
func (mp *PostgresqlProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
c := mp.connectInit()
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *PostgresqlProvider) Read(sid string) (session.RawStore, error) {
|
||||
c := p.connectInit()
|
||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
||||
var sessiondata []byte
|
||||
err := row.Scan(&sessiondata)
|
||||
@ -168,13 +135,13 @@ func (mp *PostgresqlProvider) SessionRead(sid string) (session.RawStore, error)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rs := &PostgresqlSessionStore{c: c, sid: sid, values: kv}
|
||||
rs := &PostgresqlSessionStore{c: c, sid: sid, data: kv}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// check postgresql session exist
|
||||
func (mp *PostgresqlProvider) SessionExist(sid string) bool {
|
||||
c := mp.connectInit()
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *PostgresqlProvider) Exist(sid string) bool {
|
||||
c := p.connectInit()
|
||||
defer c.Close()
|
||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
||||
var sessiondata []byte
|
||||
@ -187,9 +154,18 @@ func (mp *PostgresqlProvider) SessionExist(sid string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for postgresql session
|
||||
func (mp *PostgresqlProvider) SessionRegenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := mp.connectInit()
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *PostgresqlProvider) Destory(sid string) (err error) {
|
||||
c := p.connectInit()
|
||||
if _, err = c.Exec("DELETE FROM session where session_key=$1", sid); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *PostgresqlProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := p.connectInit()
|
||||
row := c.QueryRow("select session_data from session where session_key=$1", oldsid)
|
||||
var sessiondata []byte
|
||||
err := row.Scan(&sessiondata)
|
||||
@ -207,29 +183,13 @@ func (mp *PostgresqlProvider) SessionRegenerate(oldsid, sid string) (session.Raw
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rs := &PostgresqlSessionStore{c: c, sid: sid, values: kv}
|
||||
rs := &PostgresqlSessionStore{c: c, sid: sid, data: kv}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// delete postgresql session by sid
|
||||
func (mp *PostgresqlProvider) SessionDestroy(sid string) error {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE FROM session where session_key=$1", sid)
|
||||
c.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// delete expired values in postgresql session
|
||||
func (mp *PostgresqlProvider) SessionGC() {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime)
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// count values in postgresql session
|
||||
func (mp *PostgresqlProvider) SessionAll() int {
|
||||
c := mp.connectInit()
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *PostgresqlProvider) Count() int {
|
||||
c := p.connectInit()
|
||||
defer c.Close()
|
||||
var total int
|
||||
err := c.QueryRow("SELECT count(*) as num from session").Scan(&total)
|
||||
@ -239,6 +199,13 @@ func (mp *PostgresqlProvider) SessionAll() int {
|
||||
return total
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("postgresql", postgresqlpder)
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (mp *PostgresqlProvider) GC() {
|
||||
c := mp.connectInit()
|
||||
c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime)
|
||||
c.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("postgresql", &PostgresqlProvider{})
|
||||
}
|
||||
|
177
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.go
generated
vendored
177
Godeps/_workspace/src/github.com/macaron-contrib/session/redis/redis.go
generated
vendored
@ -16,7 +16,6 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -26,126 +25,125 @@ import (
|
||||
"github.com/macaron-contrib/session"
|
||||
)
|
||||
|
||||
var redispder = &RedisProvider{}
|
||||
|
||||
// redis max pool size
|
||||
var MAX_POOL_SIZE = 100
|
||||
|
||||
var redisPool chan redis.Conn
|
||||
|
||||
// redis session store
|
||||
// RedisSessionStore represents a redis session store implementation.
|
||||
type RedisSessionStore struct {
|
||||
p *redis.Pool
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
data map[interface{}]interface{}
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// set value in redis session
|
||||
func (rs *RedisSessionStore) Set(key, value interface{}) error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
rs.values[key] = value
|
||||
// Set sets value to given key in session.
|
||||
func (s *RedisSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value in redis session
|
||||
func (rs *RedisSessionStore) Get(key interface{}) interface{} {
|
||||
rs.lock.RLock()
|
||||
defer rs.lock.RUnlock()
|
||||
if v, ok := rs.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// Get gets value by given key in session.
|
||||
func (s *RedisSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// delete value in redis session
|
||||
func (rs *RedisSessionStore) Delete(key interface{}) error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
delete(rs.values, key)
|
||||
// Delete delete a key from session.
|
||||
func (s *RedisSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in redis session
|
||||
func (rs *RedisSessionStore) Flush() error {
|
||||
rs.lock.Lock()
|
||||
defer rs.lock.Unlock()
|
||||
rs.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
// ID returns current session ID.
|
||||
func (s *RedisSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// get redis session id
|
||||
func (rs *RedisSessionStore) SessionID() string {
|
||||
return rs.sid
|
||||
}
|
||||
|
||||
// save session values to redis
|
||||
func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
c := rs.p.Get()
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *RedisSessionStore) Release() error {
|
||||
c := s.p.Get()
|
||||
defer c.Close()
|
||||
|
||||
b, err := session.EncodeGob(rs.values)
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
c.Do("SETEX", rs.sid, rs.maxlifetime, string(b))
|
||||
_, err = c.Do("SETEX", s.sid, s.maxlifetime, string(data))
|
||||
return err
|
||||
}
|
||||
|
||||
// redis session provider
|
||||
// Flush deletes all session data.
|
||||
func (s *RedisSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// RedisProvider represents a redis session provider implementation.
|
||||
type RedisProvider struct {
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
connAddr string
|
||||
poolsize int
|
||||
password string
|
||||
poollist *redis.Pool
|
||||
}
|
||||
|
||||
// init redis session
|
||||
// savepath like redis server addr,pool size,password
|
||||
// e.g. 127.0.0.1:6379,100,astaxie
|
||||
func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
rp.maxlifetime = maxlifetime
|
||||
configs := strings.Split(savePath, ",")
|
||||
// Init initializes memory session provider.
|
||||
// connStr: <redis server addr>,<pool size>,<password>
|
||||
// e.g. 127.0.0.1:6379,100,macaron
|
||||
func (p *RedisProvider) Init(maxlifetime int64, connStr string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
configs := strings.Split(connStr, ",")
|
||||
if len(configs) > 0 {
|
||||
rp.savePath = configs[0]
|
||||
p.connAddr = configs[0]
|
||||
}
|
||||
if len(configs) > 1 {
|
||||
poolsize, err := strconv.Atoi(configs[1])
|
||||
if err != nil || poolsize <= 0 {
|
||||
rp.poolsize = MAX_POOL_SIZE
|
||||
p.poolsize = MAX_POOL_SIZE
|
||||
} else {
|
||||
rp.poolsize = poolsize
|
||||
p.poolsize = poolsize
|
||||
}
|
||||
} else {
|
||||
rp.poolsize = MAX_POOL_SIZE
|
||||
p.poolsize = MAX_POOL_SIZE
|
||||
}
|
||||
if len(configs) > 2 {
|
||||
rp.password = configs[2]
|
||||
p.password = configs[2]
|
||||
}
|
||||
rp.poollist = redis.NewPool(func() (redis.Conn, error) {
|
||||
c, err := redis.Dial("tcp", rp.savePath)
|
||||
p.poollist = redis.NewPool(func() (redis.Conn, error) {
|
||||
c, err := redis.Dial("tcp", p.connAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rp.password != "" {
|
||||
if _, err := c.Do("AUTH", rp.password); err != nil {
|
||||
if p.password != "" {
|
||||
if _, err := c.Do("AUTH", p.password); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c, err
|
||||
}, rp.poolsize)
|
||||
}, p.poolsize)
|
||||
|
||||
return rp.poollist.Get().Err()
|
||||
return p.poollist.Get().Err()
|
||||
}
|
||||
|
||||
// read redis session by sid
|
||||
func (rp *RedisProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
c := rp.poollist.Get()
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
||||
c := p.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
kvs, err := redis.String(c.Do("GET", sid))
|
||||
@ -159,13 +157,13 @@ func (rp *RedisProvider) SessionRead(sid string) (session.RawStore, error) {
|
||||
}
|
||||
}
|
||||
|
||||
rs := &RedisSessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
|
||||
rs := &RedisSessionStore{p: p.poollist, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// check redis session exist by sid
|
||||
func (rp *RedisProvider) SessionExist(sid string) bool {
|
||||
c := rp.poollist.Get()
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *RedisProvider) Exist(sid string) bool {
|
||||
c := p.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
|
||||
@ -175,19 +173,28 @@ func (rp *RedisProvider) SessionExist(sid string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for redis session
|
||||
func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := rp.poollist.Get()
|
||||
// Destory deletes a session by session ID.
|
||||
func (p *RedisProvider) Destory(sid string) error {
|
||||
c := p.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
_, err := c.Do("DEL", sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *RedisProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
c := p.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 {
|
||||
// oldsid doesn't exists, set the new sid directly
|
||||
// ignore error here, since if it return error
|
||||
// the existed value will be 0
|
||||
c.Do("SET", sid, "", "EX", rp.maxlifetime)
|
||||
c.Do("SET", sid, "", "EX", p.maxlifetime)
|
||||
} else {
|
||||
c.Do("RENAME", oldsid, sid)
|
||||
c.Do("EXPIRE", sid, rp.maxlifetime)
|
||||
c.Do("EXPIRE", sid, p.maxlifetime)
|
||||
}
|
||||
|
||||
kvs, err := redis.String(c.Do("GET", sid))
|
||||
@ -201,29 +208,19 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (session.RawStore
|
||||
}
|
||||
}
|
||||
|
||||
rs := &RedisSessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
|
||||
rs := &RedisSessionStore{p: p.poollist, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// delete redis session by id
|
||||
func (rp *RedisProvider) SessionDestroy(sid string) error {
|
||||
c := rp.poollist.Get()
|
||||
defer c.Close()
|
||||
|
||||
c.Do("DEL", sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Impelment method, no used.
|
||||
func (rp *RedisProvider) SessionGC() {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo
|
||||
func (rp *RedisProvider) SessionAll() int {
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *RedisProvider) Count() int {
|
||||
// FIXME
|
||||
return 0
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (_ *RedisProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("redis", redispder)
|
||||
session.Register("redis", &RedisProvider{})
|
||||
}
|
||||
|
186
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_cookie.go
generated
vendored
186
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_cookie.go
generated
vendored
@ -1,186 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var cookiepder = &CookieProvider{}
|
||||
|
||||
// Cookie SessionStore
|
||||
type CookieSessionStore struct {
|
||||
sid string
|
||||
values map[interface{}]interface{} // session data
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// Set value to cookie session.
|
||||
// the value are encoded as gob with hash block string.
|
||||
func (st *CookieSessionStore) Set(key, value interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get value from cookie session
|
||||
func (st *CookieSessionStore) Get(key interface{}) interface{} {
|
||||
st.lock.RLock()
|
||||
defer st.lock.RUnlock()
|
||||
if v, ok := st.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Delete value in cookie session
|
||||
func (st *CookieSessionStore) Delete(key interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
delete(st.values, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean all values in cookie session
|
||||
func (st *CookieSessionStore) Flush() error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return id of this cookie session
|
||||
func (st *CookieSessionStore) SessionID() string {
|
||||
return st.sid
|
||||
}
|
||||
|
||||
// Write cookie session to http response cookie
|
||||
func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
str, err := encodeCookie(cookiepder.block,
|
||||
cookiepder.config.SecurityKey,
|
||||
cookiepder.config.SecurityName,
|
||||
st.values)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cookie := &http.Cookie{Name: cookiepder.config.CookieName,
|
||||
Value: url.QueryEscape(str),
|
||||
Path: cookiepder.config.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: cookiepder.config.Secure,
|
||||
MaxAge: cookiepder.config.Maxage}
|
||||
http.SetCookie(w, cookie)
|
||||
return
|
||||
}
|
||||
|
||||
type cookieConfig struct {
|
||||
SecurityKey string `json:"securityKey"`
|
||||
BlockKey string `json:"blockKey"`
|
||||
SecurityName string `json:"securityName"`
|
||||
CookieName string `json:"cookieName"`
|
||||
CookiePath string `json:"cookiePath"`
|
||||
Secure bool `json:"secure"`
|
||||
Maxage int `json:"maxage"`
|
||||
}
|
||||
|
||||
// Cookie session provider
|
||||
type CookieProvider struct {
|
||||
maxlifetime int64
|
||||
config *cookieConfig
|
||||
block cipher.Block
|
||||
}
|
||||
|
||||
// Init cookie session provider with max lifetime and config json.
|
||||
// maxlifetime is ignored.
|
||||
// json config:
|
||||
// securityKey - hash string
|
||||
// blockKey - gob encode hash string. it's saved as aes crypto.
|
||||
// securityName - recognized name in encoded cookie string
|
||||
// cookieName - cookie name
|
||||
// maxage - cookie max life time.
|
||||
func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error {
|
||||
pder.config = &cookieConfig{}
|
||||
err := json.Unmarshal([]byte(config), pder.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pder.config.BlockKey == "" {
|
||||
pder.config.BlockKey = string(generateRandomKey(16))
|
||||
}
|
||||
if pder.config.SecurityName == "" {
|
||||
pder.config.SecurityName = string(generateRandomKey(20))
|
||||
}
|
||||
pder.block, err = aes.NewCipher([]byte(pder.config.BlockKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pder.maxlifetime = maxlifetime
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get SessionStore in cooke.
|
||||
// decode cooke string to map and put into SessionStore with sid.
|
||||
func (pder *CookieProvider) SessionRead(sid string) (RawStore, error) {
|
||||
maps, _ := decodeCookie(pder.block,
|
||||
pder.config.SecurityKey,
|
||||
pder.config.SecurityName,
|
||||
sid, pder.maxlifetime)
|
||||
if maps == nil {
|
||||
maps = make(map[interface{}]interface{})
|
||||
}
|
||||
rs := &CookieSessionStore{sid: sid, values: maps}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// Cookie session is always existed
|
||||
func (pder *CookieProvider) SessionExist(sid string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Implement method, no used.
|
||||
func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (RawStore, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Implement method, no used.
|
||||
func (pder *CookieProvider) SessionDestroy(sid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implement method, no used.
|
||||
func (pder *CookieProvider) SessionGC() {
|
||||
return
|
||||
}
|
||||
|
||||
// Implement method, return 0.
|
||||
func (pder *CookieProvider) SessionAll() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Implement method, no used.
|
||||
func (pder *CookieProvider) SessionUpdate(sid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("cookie", cookiepder)
|
||||
}
|
60
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_cookie_test.go
generated
vendored
60
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_cookie_test.go
generated
vendored
@ -1,60 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
// Copyright 2014 Unknwon
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCookie(t *testing.T) {
|
||||
config := &Config{
|
||||
CookieName: "gosessionid",
|
||||
Gclifetime: 3600,
|
||||
ProviderConfig: "{\"cookieName\":\"gosessionid\",\"securityKey\":\"macaroncookiehashkey\"}",
|
||||
}
|
||||
globalSessions, err := NewManager("cookie", config)
|
||||
if err != nil {
|
||||
t.Fatal("init cookie session err", err)
|
||||
}
|
||||
r, _ := http.NewRequest("GET", "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
sess, err := globalSessions.SessionStart(w, r)
|
||||
if err != nil {
|
||||
t.Fatal("start session,", err)
|
||||
}
|
||||
err = sess.Set("username", "astaxie")
|
||||
if err != nil {
|
||||
t.Fatal("set error,", err)
|
||||
}
|
||||
if username := sess.Get("username"); username != "astaxie" {
|
||||
t.Fatal("get username error")
|
||||
}
|
||||
sess.SessionRelease(w)
|
||||
if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" {
|
||||
t.Fatal("setcookie error")
|
||||
} else {
|
||||
parts := strings.Split(strings.TrimSpace(cookiestr), ";")
|
||||
for k, v := range parts {
|
||||
nameval := strings.Split(v, "=")
|
||||
if k == 0 && nameval[0] != "gosessionid" {
|
||||
t.Fatal("error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
288
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_file.go
generated
vendored
288
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_file.go
generated
vendored
@ -1,288 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
filepder = &FileProvider{}
|
||||
gcmaxlifetime int64
|
||||
)
|
||||
|
||||
// File session store
|
||||
type FileSessionStore struct {
|
||||
f *os.File
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// Set value to file session
|
||||
func (fs *FileSessionStore) Set(key, value interface{}) error {
|
||||
fs.lock.Lock()
|
||||
defer fs.lock.Unlock()
|
||||
fs.values[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get value from file session
|
||||
func (fs *FileSessionStore) Get(key interface{}) interface{} {
|
||||
fs.lock.RLock()
|
||||
defer fs.lock.RUnlock()
|
||||
if v, ok := fs.values[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Delete value in file session by given key
|
||||
func (fs *FileSessionStore) Delete(key interface{}) error {
|
||||
fs.lock.Lock()
|
||||
defer fs.lock.Unlock()
|
||||
delete(fs.values, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean all values in file session
|
||||
func (fs *FileSessionStore) Flush() error {
|
||||
fs.lock.Lock()
|
||||
defer fs.lock.Unlock()
|
||||
fs.values = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get file session store id
|
||||
func (fs *FileSessionStore) SessionID() string {
|
||||
return fs.sid
|
||||
}
|
||||
|
||||
// Write file session to local file with Gob string
|
||||
func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
b, err := EncodeGob(fs.values)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = os.Stat(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid))
|
||||
var f *os.File
|
||||
if err == nil {
|
||||
f, err = os.OpenFile(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0777)
|
||||
} else if os.IsNotExist(err) {
|
||||
f, err = os.Create(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid))
|
||||
} else {
|
||||
return
|
||||
}
|
||||
f.Truncate(0)
|
||||
f.Seek(0, 0)
|
||||
f.Write(b)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
// File session provider
|
||||
type FileProvider struct {
|
||||
lock sync.RWMutex
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
}
|
||||
|
||||
// Init file session provider.
|
||||
// savePath sets the session files path.
|
||||
func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
fp.maxlifetime = maxlifetime
|
||||
fp.savePath = savePath
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read file session by sid.
|
||||
// if file is not exist, create it.
|
||||
// the file path is generated from sid string.
|
||||
func (fp *FileProvider) SessionRead(sid string) (RawStore, error) {
|
||||
filepder.lock.Lock()
|
||||
defer filepder.lock.Unlock()
|
||||
|
||||
err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
_, err = os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
var f *os.File
|
||||
if err == nil {
|
||||
f, err = os.OpenFile(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), os.O_RDWR, 0777)
|
||||
} else if os.IsNotExist(err) {
|
||||
f, err = os.Create(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
os.Chtimes(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), time.Now(), time.Now())
|
||||
var kv map[interface{}]interface{}
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = DecodeGob(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
f.Close()
|
||||
ss := &FileSessionStore{sid: sid, values: kv}
|
||||
return ss, nil
|
||||
}
|
||||
|
||||
// Check file session exist.
|
||||
// it checkes the file named from sid exist or not.
|
||||
func (fp *FileProvider) SessionExist(sid string) bool {
|
||||
filepder.lock.Lock()
|
||||
defer filepder.lock.Unlock()
|
||||
|
||||
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
if err == nil {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all files in this save path
|
||||
func (fp *FileProvider) SessionDestroy(sid string) error {
|
||||
filepder.lock.Lock()
|
||||
defer filepder.lock.Unlock()
|
||||
os.Remove(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recycle files in save path
|
||||
func (fp *FileProvider) SessionGC() {
|
||||
filepder.lock.Lock()
|
||||
defer filepder.lock.Unlock()
|
||||
|
||||
gcmaxlifetime = fp.maxlifetime
|
||||
filepath.Walk(fp.savePath, gcpath)
|
||||
}
|
||||
|
||||
// Get active file session number.
|
||||
// it walks save path to count files.
|
||||
func (fp *FileProvider) SessionAll() int {
|
||||
a := &activeSession{}
|
||||
err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error {
|
||||
return a.visit(path, f, err)
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("filepath.Walk() returned %v\n", err)
|
||||
return 0
|
||||
}
|
||||
return a.total
|
||||
}
|
||||
|
||||
// Generate new sid for file session.
|
||||
// it delete old file and create new file named from new sid.
|
||||
func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (RawStore, error) {
|
||||
filepder.lock.Lock()
|
||||
defer filepder.lock.Unlock()
|
||||
|
||||
err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
err = os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
_, err = os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
var newf *os.File
|
||||
if err == nil {
|
||||
return nil, errors.New("newsid exist")
|
||||
} else if os.IsNotExist(err) {
|
||||
newf, err = os.Create(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
}
|
||||
|
||||
_, err = os.Stat(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1]), oldsid))
|
||||
var f *os.File
|
||||
if err == nil {
|
||||
f, err = os.OpenFile(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1]), oldsid), os.O_RDWR, 0777)
|
||||
io.Copy(newf, f)
|
||||
} else if os.IsNotExist(err) {
|
||||
newf, err = os.Create(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
f.Close()
|
||||
os.Remove(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])))
|
||||
os.Chtimes(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), time.Now(), time.Now())
|
||||
var kv map[interface{}]interface{}
|
||||
b, err := ioutil.ReadAll(newf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = DecodeGob(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ss := &FileSessionStore{sid: sid, values: kv}
|
||||
return ss, nil
|
||||
}
|
||||
|
||||
// remove file in save path if expired
|
||||
func gcpath(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if (info.ModTime().Unix() + gcmaxlifetime) < time.Now().Unix() {
|
||||
os.Remove(path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type activeSession struct {
|
||||
total int
|
||||
}
|
||||
|
||||
func (self *activeSession) visit(paths string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDir() {
|
||||
return nil
|
||||
}
|
||||
self.total = self.total + 1
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("file", filepder)
|
||||
}
|
199
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_mem.go
generated
vendored
199
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_mem.go
generated
vendored
@ -1,199 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)}
|
||||
|
||||
// memory session store.
|
||||
// it saved sessions in a map in memory.
|
||||
type MemSessionStore struct {
|
||||
sid string //session id
|
||||
timeAccessed time.Time //last access time
|
||||
value map[interface{}]interface{} //session store
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// set value to memory session
|
||||
func (st *MemSessionStore) Set(key, value interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.value[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// get value from memory session by key
|
||||
func (st *MemSessionStore) Get(key interface{}) interface{} {
|
||||
st.lock.RLock()
|
||||
defer st.lock.RUnlock()
|
||||
if v, ok := st.value[key]; ok {
|
||||
return v
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// delete in memory session by key
|
||||
func (st *MemSessionStore) Delete(key interface{}) error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
delete(st.value, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clear all values in memory session
|
||||
func (st *MemSessionStore) Flush() error {
|
||||
st.lock.Lock()
|
||||
defer st.lock.Unlock()
|
||||
st.value = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// get this id of memory session store
|
||||
func (st *MemSessionStore) SessionID() string {
|
||||
return st.sid
|
||||
}
|
||||
|
||||
// Implement method, no used.
|
||||
func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||
}
|
||||
|
||||
type MemProvider struct {
|
||||
lock sync.RWMutex // locker
|
||||
sessions map[string]*list.Element // map in memory
|
||||
list *list.List // for gc
|
||||
maxlifetime int64
|
||||
savePath string
|
||||
}
|
||||
|
||||
// init memory session
|
||||
func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||
pder.maxlifetime = maxlifetime
|
||||
pder.savePath = savePath
|
||||
return nil
|
||||
}
|
||||
|
||||
// get memory session store by sid
|
||||
func (pder *MemProvider) SessionRead(sid string) (RawStore, error) {
|
||||
pder.lock.RLock()
|
||||
if element, ok := pder.sessions[sid]; ok {
|
||||
go pder.SessionUpdate(sid)
|
||||
pder.lock.RUnlock()
|
||||
return element.Value.(*MemSessionStore), nil
|
||||
} else {
|
||||
pder.lock.RUnlock()
|
||||
pder.lock.Lock()
|
||||
newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
|
||||
element := pder.list.PushBack(newsess)
|
||||
pder.sessions[sid] = element
|
||||
pder.lock.Unlock()
|
||||
return newsess, nil
|
||||
}
|
||||
}
|
||||
|
||||
// check session store exist in memory session by sid
|
||||
func (pder *MemProvider) SessionExist(sid string) bool {
|
||||
pder.lock.RLock()
|
||||
defer pder.lock.RUnlock()
|
||||
if _, ok := pder.sessions[sid]; ok {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// generate new sid for session store in memory session
|
||||
func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (RawStore, error) {
|
||||
pder.lock.RLock()
|
||||
if element, ok := pder.sessions[oldsid]; ok {
|
||||
go pder.SessionUpdate(oldsid)
|
||||
pder.lock.RUnlock()
|
||||
pder.lock.Lock()
|
||||
element.Value.(*MemSessionStore).sid = sid
|
||||
pder.sessions[sid] = element
|
||||
delete(pder.sessions, oldsid)
|
||||
pder.lock.Unlock()
|
||||
return element.Value.(*MemSessionStore), nil
|
||||
} else {
|
||||
pder.lock.RUnlock()
|
||||
pder.lock.Lock()
|
||||
newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
|
||||
element := pder.list.PushBack(newsess)
|
||||
pder.sessions[sid] = element
|
||||
pder.lock.Unlock()
|
||||
return newsess, nil
|
||||
}
|
||||
}
|
||||
|
||||
// delete session store in memory session by id
|
||||
func (pder *MemProvider) SessionDestroy(sid string) error {
|
||||
pder.lock.Lock()
|
||||
defer pder.lock.Unlock()
|
||||
if element, ok := pder.sessions[sid]; ok {
|
||||
delete(pder.sessions, sid)
|
||||
pder.list.Remove(element)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// clean expired session stores in memory session
|
||||
func (pder *MemProvider) SessionGC() {
|
||||
pder.lock.RLock()
|
||||
for {
|
||||
element := pder.list.Back()
|
||||
if element == nil {
|
||||
break
|
||||
}
|
||||
if (element.Value.(*MemSessionStore).timeAccessed.Unix() + pder.maxlifetime) < time.Now().Unix() {
|
||||
pder.lock.RUnlock()
|
||||
pder.lock.Lock()
|
||||
pder.list.Remove(element)
|
||||
delete(pder.sessions, element.Value.(*MemSessionStore).sid)
|
||||
pder.lock.Unlock()
|
||||
pder.lock.RLock()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
pder.lock.RUnlock()
|
||||
}
|
||||
|
||||
// get count number of memory session
|
||||
func (pder *MemProvider) SessionAll() int {
|
||||
return pder.list.Len()
|
||||
}
|
||||
|
||||
// expand time of session store by id in memory session
|
||||
func (pder *MemProvider) SessionUpdate(sid string) error {
|
||||
pder.lock.Lock()
|
||||
defer pder.lock.Unlock()
|
||||
if element, ok := pder.sessions[sid]; ok {
|
||||
element.Value.(*MemSessionStore).timeAccessed = time.Now()
|
||||
pder.list.MoveToFront(element)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("memory", mempder)
|
||||
}
|
59
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_mem_test.go
generated
vendored
59
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_mem_test.go
generated
vendored
@ -1,59 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
// Copyright 2014 Unknwon
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestMem(t *testing.T) {
|
||||
Convey("Memory provider", t, func() {
|
||||
config := &Config{
|
||||
CookieName: "gosessionid",
|
||||
Gclifetime: 10,
|
||||
}
|
||||
globalSessions, err := NewManager("memory", config)
|
||||
So(err, ShouldBeNil)
|
||||
go globalSessions.GC()
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
req, err := http.NewRequest("GET", "/", nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
sess, err := globalSessions.SessionStart(resp, req)
|
||||
if err != nil {
|
||||
t.Fatal("start session,", err)
|
||||
}
|
||||
defer sess.SessionRelease(resp)
|
||||
|
||||
So(sess.Set("username", "Unknwon"), ShouldBeNil)
|
||||
So(sess.Get("username"), ShouldEqual, "Unknwon")
|
||||
|
||||
cookiestr := resp.Header().Get("Set-Cookie")
|
||||
So(cookiestr, ShouldNotBeEmpty)
|
||||
parts := strings.Split(strings.TrimSpace(cookiestr), ";")
|
||||
for _, v := range parts {
|
||||
nameval := strings.Split(v, "=")
|
||||
So(nameval[0], ShouldEqual, "gosessionid")
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
132
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_test.go
generated
vendored
132
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_test.go
generated
vendored
@ -1,132 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_gob(t *testing.T) {
|
||||
a := make(map[interface{}]interface{})
|
||||
a["username"] = "astaxie"
|
||||
a[12] = 234
|
||||
a["user"] = User{"asta", "xie"}
|
||||
b, err := EncodeGob(a)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
c, err := DecodeGob(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if len(c) == 0 {
|
||||
t.Error("decodeGob empty")
|
||||
}
|
||||
if c["username"] != "astaxie" {
|
||||
t.Error("decode string error")
|
||||
}
|
||||
if c[12] != 234 {
|
||||
t.Error("decode int error")
|
||||
}
|
||||
if c["user"].(User).Username != "asta" {
|
||||
t.Error("decode struct error")
|
||||
}
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Username string
|
||||
NickName string
|
||||
}
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
str := generateRandomKey(20)
|
||||
if len(str) != 20 {
|
||||
t.Fatal("generate length is not equal to 20")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieEncodeDecode(t *testing.T) {
|
||||
hashKey := "testhashKey"
|
||||
blockkey := generateRandomKey(16)
|
||||
block, err := aes.NewCipher(blockkey)
|
||||
if err != nil {
|
||||
t.Fatal("NewCipher:", err)
|
||||
}
|
||||
securityName := string(generateRandomKey(20))
|
||||
val := make(map[interface{}]interface{})
|
||||
val["name"] = "astaxie"
|
||||
val["gender"] = "male"
|
||||
str, err := encodeCookie(block, hashKey, securityName, val)
|
||||
if err != nil {
|
||||
t.Fatal("encodeCookie:", err)
|
||||
}
|
||||
dst := make(map[interface{}]interface{})
|
||||
dst, err = decodeCookie(block, hashKey, securityName, str, 3600)
|
||||
if err != nil {
|
||||
t.Fatal("decodeCookie", err)
|
||||
}
|
||||
if dst["name"] != "astaxie" {
|
||||
t.Fatal("dst get map error")
|
||||
}
|
||||
if dst["gender"] != "male" {
|
||||
t.Fatal("dst get map error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseConfig(t *testing.T) {
|
||||
s := `{"cookieName":"gosessionid","gclifetime":3600}`
|
||||
cf := new(Config)
|
||||
cf.EnableSetCookie = true
|
||||
err := json.Unmarshal([]byte(s), cf)
|
||||
if err != nil {
|
||||
t.Fatal("parse json error,", err)
|
||||
}
|
||||
if cf.CookieName != "gosessionid" {
|
||||
t.Fatal("parseconfig get cookiename error")
|
||||
}
|
||||
if cf.Gclifetime != 3600 {
|
||||
t.Fatal("parseconfig get gclifetime error")
|
||||
}
|
||||
|
||||
cc := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`
|
||||
cf2 := new(Config)
|
||||
cf2.EnableSetCookie = true
|
||||
err = json.Unmarshal([]byte(cc), cf2)
|
||||
if err != nil {
|
||||
t.Fatal("parse json error,", err)
|
||||
}
|
||||
if cf2.CookieName != "gosessionid" {
|
||||
t.Fatal("parseconfig get cookiename error")
|
||||
}
|
||||
if cf2.Gclifetime != 3600 {
|
||||
t.Fatal("parseconfig get gclifetime error")
|
||||
}
|
||||
if cf2.EnableSetCookie != false {
|
||||
t.Fatal("parseconfig get enableSetCookie error")
|
||||
}
|
||||
cconfig := new(cookieConfig)
|
||||
err = json.Unmarshal([]byte(cf2.ProviderConfig), cconfig)
|
||||
if err != nil {
|
||||
t.Fatal("parse ProviderConfig err,", err)
|
||||
}
|
||||
if cconfig.CookieName != "gosessionid" {
|
||||
t.Fatal("ProviderConfig get cookieName error")
|
||||
}
|
||||
if cconfig.SecurityKey != "beegocookiehashkey" {
|
||||
t.Fatal("ProviderConfig get securityKey error")
|
||||
}
|
||||
}
|
231
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_utils.go
generated
vendored
231
Godeps/_workspace/src/github.com/macaron-contrib/session/sess_utils.go
generated
vendored
@ -1,231 +0,0 @@
|
||||
// Copyright 2013 Beego Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
r "math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register([]interface{}{})
|
||||
gob.Register(map[int]interface{}{})
|
||||
gob.Register(map[string]interface{}{})
|
||||
gob.Register(map[interface{}]interface{}{})
|
||||
gob.Register(map[string]string{})
|
||||
gob.Register(map[int]string{})
|
||||
gob.Register(map[int]int{})
|
||||
gob.Register(map[int]int64{})
|
||||
}
|
||||
|
||||
// RandomCreateBytes generate random []byte by specify chars.
|
||||
func RandomCreateBytes(n int, alphabets ...byte) []byte {
|
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
var bytes = make([]byte, n)
|
||||
var randby bool
|
||||
if num, err := rand.Read(bytes); num != n || err != nil {
|
||||
r.Seed(time.Now().UnixNano())
|
||||
randby = true
|
||||
}
|
||||
for i, b := range bytes {
|
||||
if len(alphabets) == 0 {
|
||||
if randby {
|
||||
bytes[i] = alphanum[r.Intn(len(alphanum))]
|
||||
} else {
|
||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||
}
|
||||
} else {
|
||||
if randby {
|
||||
bytes[i] = alphabets[r.Intn(len(alphabets))]
|
||||
} else {
|
||||
bytes[i] = alphabets[b%byte(len(alphabets))]
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
||||
for _, v := range obj {
|
||||
gob.Register(v)
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
enc := gob.NewEncoder(buf)
|
||||
err := enc.Encode(obj)
|
||||
if err != nil {
|
||||
return []byte(""), err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func DecodeGob(encoded []byte) (map[interface{}]interface{}, error) {
|
||||
buf := bytes.NewBuffer(encoded)
|
||||
dec := gob.NewDecoder(buf)
|
||||
var out map[interface{}]interface{}
|
||||
err := dec.Decode(&out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// generateRandomKey creates a random key with the given strength.
|
||||
func generateRandomKey(strength int) []byte {
|
||||
k := make([]byte, strength)
|
||||
if n, err := io.ReadFull(rand.Reader, k); n != strength || err != nil {
|
||||
return RandomCreateBytes(strength)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
// Encryption -----------------------------------------------------------------
|
||||
|
||||
// encrypt encrypts a value using the given block in counter mode.
|
||||
//
|
||||
// A random initialization vector (http://goo.gl/zF67k) with the length of the
|
||||
// block size is prepended to the resulting ciphertext.
|
||||
func encrypt(block cipher.Block, value []byte) ([]byte, error) {
|
||||
iv := generateRandomKey(block.BlockSize())
|
||||
if iv == nil {
|
||||
return nil, errors.New("encrypt: failed to generate random iv")
|
||||
}
|
||||
// Encrypt it.
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
stream.XORKeyStream(value, value)
|
||||
// Return iv + ciphertext.
|
||||
return append(iv, value...), nil
|
||||
}
|
||||
|
||||
// decrypt decrypts a value using the given block in counter mode.
|
||||
//
|
||||
// The value to be decrypted must be prepended by a initialization vector
|
||||
// (http://goo.gl/zF67k) with the length of the block size.
|
||||
func decrypt(block cipher.Block, value []byte) ([]byte, error) {
|
||||
size := block.BlockSize()
|
||||
if len(value) > size {
|
||||
// Extract iv.
|
||||
iv := value[:size]
|
||||
// Extract ciphertext.
|
||||
value = value[size:]
|
||||
// Decrypt it.
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
stream.XORKeyStream(value, value)
|
||||
return value, nil
|
||||
}
|
||||
return nil, errors.New("decrypt: the value could not be decrypted")
|
||||
}
|
||||
|
||||
func encodeCookie(block cipher.Block, hashKey, name string, value map[interface{}]interface{}) (string, error) {
|
||||
var err error
|
||||
var b []byte
|
||||
// 1. EncodeGob.
|
||||
if b, err = EncodeGob(value); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 2. Encrypt (optional).
|
||||
if b, err = encrypt(block, b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = encode(b)
|
||||
// 3. Create MAC for "name|date|value". Extra pipe to be used later.
|
||||
b = []byte(fmt.Sprintf("%s|%d|%s|", name, time.Now().UTC().Unix(), b))
|
||||
h := hmac.New(sha1.New, []byte(hashKey))
|
||||
h.Write(b)
|
||||
sig := h.Sum(nil)
|
||||
// Append mac, remove name.
|
||||
b = append(b, sig...)[len(name)+1:]
|
||||
// 4. Encode to base64.
|
||||
b = encode(b)
|
||||
// Done.
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func decodeCookie(block cipher.Block, hashKey, name, value string, gcmaxlifetime int64) (map[interface{}]interface{}, error) {
|
||||
// 1. Decode from base64.
|
||||
b, err := decode([]byte(value))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 2. Verify MAC. Value is "date|value|mac".
|
||||
parts := bytes.SplitN(b, []byte("|"), 3)
|
||||
if len(parts) != 3 {
|
||||
return nil, errors.New("Decode: invalid value %v")
|
||||
}
|
||||
|
||||
b = append([]byte(name+"|"), b[:len(b)-len(parts[2])]...)
|
||||
h := hmac.New(sha1.New, []byte(hashKey))
|
||||
h.Write(b)
|
||||
sig := h.Sum(nil)
|
||||
if len(sig) != len(parts[2]) || subtle.ConstantTimeCompare(sig, parts[2]) != 1 {
|
||||
return nil, errors.New("Decode: the value is not valid")
|
||||
}
|
||||
// 3. Verify date ranges.
|
||||
var t1 int64
|
||||
if t1, err = strconv.ParseInt(string(parts[0]), 10, 64); err != nil {
|
||||
return nil, errors.New("Decode: invalid timestamp")
|
||||
}
|
||||
t2 := time.Now().UTC().Unix()
|
||||
if t1 > t2 {
|
||||
return nil, errors.New("Decode: timestamp is too new")
|
||||
}
|
||||
if t1 < t2-gcmaxlifetime {
|
||||
return nil, errors.New("Decode: expired timestamp")
|
||||
}
|
||||
// 4. Decrypt (optional).
|
||||
b, err = decode(parts[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if b, err = decrypt(block, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 5. DecodeGob.
|
||||
if dst, err := DecodeGob(b); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return dst, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Encoding -------------------------------------------------------------------
|
||||
|
||||
// encode encodes a value using base64.
|
||||
func encode(value []byte) []byte {
|
||||
encoded := make([]byte, base64.URLEncoding.EncodedLen(len(value)))
|
||||
base64.URLEncoding.Encode(encoded, value)
|
||||
return encoded
|
||||
}
|
||||
|
||||
// decode decodes a cookie using base64.
|
||||
func decode(value []byte) ([]byte, error) {
|
||||
decoded := make([]byte, base64.URLEncoding.DecodedLen(len(value)))
|
||||
b, err := base64.URLEncoding.Decode(decoded, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decoded[:b], nil
|
||||
}
|
615
Godeps/_workspace/src/github.com/macaron-contrib/session/session.go
generated
vendored
615
Godeps/_workspace/src/github.com/macaron-contrib/session/session.go
generated
vendored
@ -16,10 +16,9 @@
|
||||
// Package session a middleware that provides the session manager of Macaron.
|
||||
package session
|
||||
|
||||
// NOTE: last sync fc6b9ce on Nov 4, 2014.
|
||||
// NOTE: last sync 000033e on Nov 4, 2014.
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -29,30 +28,74 @@ import (
|
||||
"github.com/Unknwon/macaron"
|
||||
)
|
||||
|
||||
const _VERSION = "0.1.1"
|
||||
|
||||
func Version() string {
|
||||
return "0.0.5"
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
// RawStore is the interface that operates the session data.
|
||||
type RawStore interface {
|
||||
Set(key, value interface{}) error //set session value
|
||||
Get(key interface{}) interface{} //get session value
|
||||
Delete(key interface{}) error //delete session value
|
||||
SessionID() string //back current sessionID
|
||||
SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data
|
||||
Flush() error //delete all data
|
||||
// Set sets value to given key in session.
|
||||
Set(key, value interface{}) error
|
||||
// Get gets value by given key in session.
|
||||
Get(key interface{}) interface{}
|
||||
// Delete delete a key from session.
|
||||
Delete(key interface{}) error
|
||||
// ID returns current session ID.
|
||||
ID() string
|
||||
// Release releases session resource and save data to provider.
|
||||
Release() error
|
||||
// Flush deletes all session data.
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// Store contains all data for one session process with specific id.
|
||||
// Store is the interface that contains all data for one session process with specific ID.
|
||||
type Store interface {
|
||||
RawStore
|
||||
GetActiveSession() int
|
||||
// Read returns raw session store by session ID.
|
||||
Read(sid string) (RawStore, error)
|
||||
// Destory deletes a session.
|
||||
Destory(*macaron.Context) error
|
||||
// RegenerateId regenerates a session store from old session ID to new one.
|
||||
RegenerateId(*macaron.Context) (RawStore, error)
|
||||
// Count counts and returns number of sessions.
|
||||
Count() int
|
||||
// GC calls GC to clean expired sessions.
|
||||
GC()
|
||||
}
|
||||
|
||||
type store struct {
|
||||
RawStore
|
||||
*Manager
|
||||
}
|
||||
|
||||
var _ Store = &store{}
|
||||
|
||||
// Options represents a struct for specifying configuration options for the session middleware.
|
||||
type Options struct {
|
||||
// Name of provider. Default is memory.
|
||||
// Name of provider. Default is "memory".
|
||||
Provider string
|
||||
// Provider configuration string.
|
||||
Config
|
||||
// Provider configuration, it's corresponding to provider.
|
||||
ProviderConfig string
|
||||
// Cookie name to save session ID. Default is "MacaronSession".
|
||||
CookieName string
|
||||
// Cookie path to store. Default is "/".
|
||||
CookiePath string
|
||||
// GC interval time in seconds. Default is 3600.
|
||||
Gclifetime int64
|
||||
// Max life time in seconds. Default is whatever GC interval time is.
|
||||
Maxlifetime int64
|
||||
// Use HTTPS only. Default is false.
|
||||
Secure bool
|
||||
// Cookie life time. Default is 0.
|
||||
CookieLifeTime int
|
||||
// Cookie domain name. Default is empty.
|
||||
Domain string
|
||||
// Session ID length. Default is 16.
|
||||
IDLength int
|
||||
// Configuration section name. Default is "session".
|
||||
Section string
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
@ -60,32 +103,266 @@ func prepareOptions(options []Options) Options {
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
|
||||
// Defaults
|
||||
if len(opt.Provider) == 0 {
|
||||
opt.Provider = "memory"
|
||||
if len(opt.Section) == 0 {
|
||||
opt.Section = "session"
|
||||
}
|
||||
sec := macaron.Config().Section(opt.Section)
|
||||
|
||||
if len(opt.Provider) == 0 {
|
||||
opt.Provider = sec.Key("PROVIDER").MustString("memory")
|
||||
}
|
||||
if len(opt.ProviderConfig) == 0 && opt.Provider == "file" {
|
||||
opt.ProviderConfig = sec.Key("PROVIDER_CONFIG").MustString("data/sessions")
|
||||
}
|
||||
opt.EnableSetCookie = true
|
||||
if len(opt.CookieName) == 0 {
|
||||
opt.CookieName = "MacaronSession"
|
||||
opt.CookieName = sec.Key("COOKIE_NAME").MustString("MacaronSession")
|
||||
}
|
||||
if len(opt.CookiePath) == 0 {
|
||||
opt.CookiePath = "/"
|
||||
opt.CookiePath = sec.Key("COOKIE_PATH").MustString("/")
|
||||
}
|
||||
if opt.Gclifetime == 0 {
|
||||
opt.Gclifetime = 3600
|
||||
opt.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(3600)
|
||||
}
|
||||
if opt.Maxlifetime == 0 {
|
||||
opt.Maxlifetime = opt.Gclifetime
|
||||
opt.Maxlifetime = sec.Key("MAX_LIFE_TIME").MustInt64(opt.Gclifetime)
|
||||
}
|
||||
|
||||
if opt.SessionIdLength == 0 {
|
||||
opt.SessionIdLength = 16
|
||||
if !opt.Secure {
|
||||
opt.Secure = sec.Key("SECURE").MustBool()
|
||||
}
|
||||
if opt.CookieLifeTime == 0 {
|
||||
opt.CookieLifeTime = sec.Key("COOKIE_LIFE_TIME").MustInt()
|
||||
}
|
||||
if len(opt.Domain) == 0 {
|
||||
opt.Domain = sec.Key("DOMAIN").String()
|
||||
}
|
||||
if opt.IDLength == 0 {
|
||||
opt.IDLength = sec.Key("ID_LENGTH").MustInt(16)
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// Sessioner is a middleware that maps a session.SessionStore service into the Macaron handler chain.
|
||||
// An single variadic session.Options struct can be optionally provided to configure.
|
||||
func Sessioner(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
manager, err := NewManager(opt.Provider, opt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go manager.startGC()
|
||||
|
||||
return func(ctx *macaron.Context) {
|
||||
sess, err := manager.Start(ctx)
|
||||
if err != nil {
|
||||
panic("session: " + err.Error())
|
||||
}
|
||||
|
||||
// Get flash.
|
||||
vals, _ := url.ParseQuery(ctx.GetCookie("macaron_flash"))
|
||||
if len(vals) > 0 {
|
||||
f := &Flash{Values: vals}
|
||||
f.ErrorMsg = f.Get("error")
|
||||
f.SuccessMsg = f.Get("success")
|
||||
f.InfoMsg = f.Get("info")
|
||||
f.WarningMsg = f.Get("warning")
|
||||
ctx.Data["Flash"] = f
|
||||
ctx.SetCookie("macaron_flash", "", -1, opt.CookiePath)
|
||||
}
|
||||
|
||||
f := &Flash{ctx, url.Values{}, "", "", "", ""}
|
||||
ctx.Resp.Before(func(macaron.ResponseWriter) {
|
||||
if flash := f.Encode(); len(flash) > 0 {
|
||||
ctx.SetCookie("macaron_flash", flash, 0, opt.CookiePath)
|
||||
}
|
||||
})
|
||||
|
||||
ctx.Map(f)
|
||||
s := store{
|
||||
RawStore: sess,
|
||||
Manager: manager,
|
||||
}
|
||||
|
||||
ctx.MapTo(s, (*Store)(nil))
|
||||
|
||||
ctx.Next()
|
||||
|
||||
if sess.Release() != nil {
|
||||
panic("session: " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Provider is the interface that provides session manipulations.
|
||||
type Provider interface {
|
||||
// Init initializes session provider.
|
||||
Init(gclifetime int64, config string) error
|
||||
// Read returns raw session store by session ID.
|
||||
Read(sid string) (RawStore, error)
|
||||
// Exist returns true if session with given ID exists.
|
||||
Exist(sid string) bool
|
||||
// Destory deletes a session by session ID.
|
||||
Destory(sid string) error
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
Regenerate(oldsid, sid string) (RawStore, error)
|
||||
// Count counts and returns number of sessions.
|
||||
Count() int
|
||||
// GC calls GC to clean expired sessions.
|
||||
GC()
|
||||
}
|
||||
|
||||
var providers = make(map[string]Provider)
|
||||
|
||||
// Register registers a provider.
|
||||
func Register(name string, provider Provider) {
|
||||
if provider == nil {
|
||||
panic("session: cannot register provider with nil value")
|
||||
}
|
||||
if _, dup := providers[name]; dup {
|
||||
panic(fmt.Errorf("session: cannot register provider '%s' twice", name))
|
||||
}
|
||||
providers[name] = provider
|
||||
}
|
||||
|
||||
// _____
|
||||
// / \ _____ ____ _____ ____ ___________
|
||||
// / \ / \\__ \ / \\__ \ / ___\_/ __ \_ __ \
|
||||
// / Y \/ __ \| | \/ __ \_/ /_/ > ___/| | \/
|
||||
// \____|__ (____ /___| (____ /\___ / \___ >__|
|
||||
// \/ \/ \/ \//_____/ \/
|
||||
|
||||
// Manager represents a struct that contains session provider and its configuration.
|
||||
type Manager struct {
|
||||
provider Provider
|
||||
opt Options
|
||||
}
|
||||
|
||||
// NewManager creates and returns a new session manager by given provider name and configuration.
|
||||
// It panics when given provider isn't registered.
|
||||
func NewManager(name string, opt Options) (*Manager, error) {
|
||||
p, ok := providers[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("session: unknown provider ‘%q’(forgotten import?)", name)
|
||||
}
|
||||
if err := p.Init(opt.Maxlifetime, opt.ProviderConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Manager{p, opt}, nil
|
||||
}
|
||||
|
||||
// sessionId generates a new session ID with rand string, unix nano time, remote addr by hash function.
|
||||
func (m *Manager) sessionId() string {
|
||||
return hex.EncodeToString(generateRandomKey(m.opt.IDLength))
|
||||
}
|
||||
|
||||
// Start starts a session by generating new one
|
||||
// or retrieve existence one by reading session ID from HTTP request if it's valid.
|
||||
func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) {
|
||||
sid := ctx.GetCookie(m.opt.CookieName)
|
||||
if len(sid) > 0 && m.provider.Exist(sid) {
|
||||
return m.provider.Read(sid)
|
||||
}
|
||||
|
||||
sid = m.sessionId()
|
||||
sess, err := m.provider.Read(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Value: sid,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: m.opt.Secure,
|
||||
Domain: m.opt.Domain,
|
||||
}
|
||||
if m.opt.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = m.opt.CookieLifeTime
|
||||
}
|
||||
http.SetCookie(ctx.Resp, cookie)
|
||||
ctx.Req.AddCookie(cookie)
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (m *Manager) Read(sid string) (RawStore, error) {
|
||||
return m.provider.Read(sid)
|
||||
}
|
||||
|
||||
// Destory deletes a session by given ID.
|
||||
func (m *Manager) Destory(ctx *macaron.Context) error {
|
||||
sid := ctx.GetCookie(m.opt.CookieName)
|
||||
if len(sid) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.provider.Destory(sid); err != nil {
|
||||
return err
|
||||
}
|
||||
cookie := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Expires: time.Now(),
|
||||
MaxAge: -1,
|
||||
}
|
||||
http.SetCookie(ctx.Resp, cookie)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegenerateId regenerates a session store from old session ID to new one.
|
||||
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
|
||||
sid := m.sessionId()
|
||||
oldsid := ctx.GetCookie(m.opt.CookieName)
|
||||
if len(oldsid) == 0 {
|
||||
sess, err = m.provider.Read(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
sess, err = m.provider.Regenerate(oldsid, sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ck := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Value: sid,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: m.opt.Secure,
|
||||
Domain: m.opt.Domain,
|
||||
}
|
||||
if m.opt.CookieLifeTime >= 0 {
|
||||
ck.MaxAge = m.opt.CookieLifeTime
|
||||
}
|
||||
http.SetCookie(ctx.Resp, ck)
|
||||
ctx.Req.AddCookie(ck)
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (m *Manager) Count() int {
|
||||
return m.provider.Count()
|
||||
}
|
||||
|
||||
// GC starts GC job in a certain period.
|
||||
func (m *Manager) GC() {
|
||||
m.provider.GC()
|
||||
}
|
||||
|
||||
// startGC starts GC job in a certain period.
|
||||
func (m *Manager) startGC() {
|
||||
m.GC()
|
||||
time.AfterFunc(time.Duration(m.opt.Gclifetime)*time.Second, func() { m.startGC() })
|
||||
}
|
||||
|
||||
// SetSecure indicates whether to set cookie with HTTPS or not.
|
||||
func (m *Manager) SetSecure(secure bool) {
|
||||
m.opt.Secure = secure
|
||||
}
|
||||
|
||||
// ___________.____ _____ _________ ___ ___
|
||||
// \_ _____/| | / _ \ / _____// | \
|
||||
// | __) | | / /_\ \ \_____ \/ ~ \
|
||||
@ -132,289 +409,3 @@ func (f *Flash) Success(msg string, current ...bool) {
|
||||
f.SuccessMsg = msg
|
||||
f.set("success", msg, current...)
|
||||
}
|
||||
|
||||
type store struct {
|
||||
RawStore
|
||||
*Manager
|
||||
}
|
||||
|
||||
// Sessioner is a middleware that maps a session.SessionStore service into the Macaron handler chain.
|
||||
// An single variadic session.Options struct can be optionally provided to configure.
|
||||
func Sessioner(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
manager, err := NewManager(opt.Provider, &opt.Config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go manager.GC()
|
||||
|
||||
return func(ctx *macaron.Context) {
|
||||
// FIXME: should I panic for error?
|
||||
sess, _ := manager.SessionStart(ctx.Resp, ctx.Req.Request)
|
||||
|
||||
// Get flash.
|
||||
vals, _ := url.ParseQuery(ctx.GetCookie("macaron_flash"))
|
||||
if len(vals) > 0 {
|
||||
f := &Flash{Values: vals}
|
||||
f.ErrorMsg = f.Get("error")
|
||||
f.SuccessMsg = f.Get("success")
|
||||
f.InfoMsg = f.Get("info")
|
||||
f.WarningMsg = f.Get("warning")
|
||||
ctx.Data["Flash"] = f
|
||||
ctx.SetCookie("macaron_flash", "", -1, opt.CookiePath)
|
||||
}
|
||||
|
||||
f := &Flash{ctx, url.Values{}, "", "", "", ""}
|
||||
ctx.Resp.Before(func(macaron.ResponseWriter) {
|
||||
sess.SessionRelease(ctx.Resp)
|
||||
|
||||
if flash := f.Encode(); len(flash) > 0 {
|
||||
ctx.SetCookie("macaron_flash", flash, 0, opt.CookiePath)
|
||||
}
|
||||
})
|
||||
|
||||
ctx.Map(f)
|
||||
s := store{
|
||||
RawStore: sess,
|
||||
Manager: manager,
|
||||
}
|
||||
ctx.MapTo(s, (*Store)(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// Provider contains global session methods and saved SessionStores.
|
||||
// it can operate a SessionStore by its id.
|
||||
type Provider interface {
|
||||
SessionInit(gclifetime int64, config string) error
|
||||
SessionRead(sid string) (RawStore, error)
|
||||
SessionExist(sid string) bool
|
||||
SessionRegenerate(oldsid, sid string) (RawStore, error)
|
||||
SessionDestroy(sid string) error
|
||||
SessionAll() int //get all active session
|
||||
SessionGC()
|
||||
}
|
||||
|
||||
var provides = make(map[string]Provider)
|
||||
|
||||
// Register makes a session provide available by the provided name.
|
||||
// If Register is called twice with the same name or if driver is nil,
|
||||
// it panics.
|
||||
func Register(name string, provide Provider) {
|
||||
if provide == nil {
|
||||
panic("session: Register provide is nil")
|
||||
}
|
||||
if _, dup := provides[name]; dup {
|
||||
panic("session: Register called twice for provider " + name)
|
||||
}
|
||||
provides[name] = provide
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
CookieName string `json:"cookieName"`
|
||||
CookiePath string `json:"cookiePath"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Manager contains Provider and its configuration.
|
||||
type Manager struct {
|
||||
provider Provider
|
||||
config *Config
|
||||
}
|
||||
|
||||
// Create new Manager with provider name and json config string.
|
||||
// provider name:
|
||||
// 1. cookie
|
||||
// 2. file
|
||||
// 3. memory
|
||||
// 4. redis
|
||||
// 5. mysql
|
||||
// json config:
|
||||
// 1. is https default false
|
||||
// 2. hashfunc default sha1
|
||||
// 3. hashkey default beegosessionkey
|
||||
// 4. maxage default is none
|
||||
func NewManager(provideName string, config *Config) (*Manager, error) {
|
||||
provider, ok := provides[provideName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("session: unknown provide %q (forgotten import?)", provideName)
|
||||
}
|
||||
|
||||
config.EnableSetCookie = true
|
||||
if config.Maxlifetime == 0 {
|
||||
config.Maxlifetime = config.Gclifetime
|
||||
}
|
||||
if err := provider.SessionInit(config.Maxlifetime, config.ProviderConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Manager{
|
||||
provider: provider,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start session. generate or read the session id from http request.
|
||||
// if session id exists, return SessionStore with this id.
|
||||
func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session RawStore, _ error) {
|
||||
cookie, err := r.Cookie(manager.config.CookieName)
|
||||
if err != nil || len(cookie.Value) == 0 {
|
||||
sid, err := manager.sessionId(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session, err = manager.provider.SessionRead(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cookie = &http.Cookie{Name: manager.config.CookieName,
|
||||
Value: url.QueryEscape(sid),
|
||||
Path: manager.config.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: manager.config.Secure,
|
||||
Domain: manager.config.Domain,
|
||||
}
|
||||
if manager.config.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = manager.config.CookieLifeTime
|
||||
}
|
||||
if manager.config.EnableSetCookie {
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
r.AddCookie(cookie)
|
||||
} else {
|
||||
sid, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if manager.provider.SessionExist(sid) {
|
||||
session, err = manager.provider.SessionRead(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
sid, err = manager.sessionId(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session, err = manager.provider.SessionRead(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cookie = &http.Cookie{Name: manager.config.CookieName,
|
||||
Value: url.QueryEscape(sid),
|
||||
Path: manager.config.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: manager.config.Secure,
|
||||
Domain: manager.config.Domain,
|
||||
}
|
||||
if manager.config.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = manager.config.CookieLifeTime
|
||||
}
|
||||
if manager.config.EnableSetCookie {
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
r.AddCookie(cookie)
|
||||
}
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// Destroy session by its id in http request cookie.
|
||||
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie(manager.config.CookieName)
|
||||
if err != nil || cookie.Value == "" {
|
||||
return
|
||||
} else {
|
||||
manager.provider.SessionDestroy(cookie.Value)
|
||||
expiration := time.Now()
|
||||
cookie := http.Cookie{Name: manager.config.CookieName,
|
||||
Path: manager.config.CookiePath,
|
||||
HttpOnly: true,
|
||||
Expires: expiration,
|
||||
MaxAge: -1}
|
||||
http.SetCookie(w, &cookie)
|
||||
}
|
||||
}
|
||||
|
||||
// Get SessionStore by its id.
|
||||
func (manager *Manager) GetSessionStore(sid string) (sessions RawStore, err error) {
|
||||
sessions, err = manager.provider.SessionRead(sid)
|
||||
return
|
||||
}
|
||||
|
||||
// Start session gc process.
|
||||
// it can do gc in times after gc lifetime.
|
||||
func (manager *Manager) GC() {
|
||||
manager.provider.SessionGC()
|
||||
time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() })
|
||||
}
|
||||
|
||||
// Regenerate a session id for this SessionStore who's id is saving in http request.
|
||||
func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Request) (session RawStore) {
|
||||
sid, err := manager.sessionId(r)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cookie, err := r.Cookie(manager.config.CookieName)
|
||||
if err != nil && cookie.Value == "" {
|
||||
// delete old cookie
|
||||
session, err = manager.provider.SessionRead(sid)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
cookie = &http.Cookie{Name: manager.config.CookieName,
|
||||
Value: url.QueryEscape(sid),
|
||||
Path: manager.config.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: manager.config.Secure,
|
||||
Domain: manager.config.Domain,
|
||||
}
|
||||
} else {
|
||||
oldsid, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
session, err = manager.provider.SessionRegenerate(oldsid, sid)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
cookie.Value = url.QueryEscape(sid)
|
||||
cookie.HttpOnly = true
|
||||
cookie.Path = "/"
|
||||
}
|
||||
if manager.config.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = manager.config.CookieLifeTime
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
r.AddCookie(cookie)
|
||||
return session
|
||||
}
|
||||
|
||||
// Get all active sessions count number.
|
||||
func (manager *Manager) GetActiveSession() int {
|
||||
return manager.provider.SessionAll()
|
||||
}
|
||||
|
||||
// Set cookie with https.
|
||||
func (manager *Manager) SetSecure(secure bool) {
|
||||
manager.config.Secure = secure
|
||||
}
|
||||
|
||||
// generate session id with rand string, unix nano time, remote addr by hash function.
|
||||
func (manager *Manager) sessionId(r *http.Request) (string, error) {
|
||||
b := make([]byte, manager.config.SessionIdLength)
|
||||
n, err := rand.Read(b)
|
||||
if n != len(b) || err != nil {
|
||||
return "", fmt.Errorf("fail to read from the system CSPRNG.")
|
||||
}
|
||||
return hex.EncodeToString(b), nil
|
||||
}
|
||||
|
BIN
grafana-pro
BIN
grafana-pro
Binary file not shown.
@ -37,10 +37,7 @@ func newMacaron() *macaron.Macaron {
|
||||
mapStatic(m, "public/app", "app")
|
||||
mapStatic(m, "public/img", "img")
|
||||
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: setting.SessionProvider,
|
||||
Config: *setting.SessionConfig,
|
||||
}))
|
||||
m.Use(session.Sessioner(setting.SessionOptions))
|
||||
|
||||
m.Use(macaron.Renderer(macaron.RenderOptions{
|
||||
Directory: path.Join(setting.StaticRootPath, "views"),
|
||||
|
@ -54,8 +54,7 @@ var (
|
||||
StaticRootPath string
|
||||
|
||||
// Session settings.
|
||||
SessionProvider string
|
||||
SessionConfig *session.Config
|
||||
SessionOptions session.Options
|
||||
|
||||
// Global setting objects.
|
||||
Cfg *goconfig.ConfigFile
|
||||
@ -149,19 +148,18 @@ func NewConfigContext() {
|
||||
}
|
||||
|
||||
func initSessionService() {
|
||||
SessionProvider = Cfg.MustValueRange("session", "provider", "memory", []string{"memory", "file"})
|
||||
|
||||
SessionConfig = new(session.Config)
|
||||
SessionConfig.ProviderConfig = strings.Trim(Cfg.MustValue("session", "provider_config"), "\" ")
|
||||
SessionConfig.CookieName = Cfg.MustValue("session", "cookie_name", "grafana_pro_sess")
|
||||
SessionConfig.CookiePath = AppSubUrl
|
||||
SessionConfig.Secure = Cfg.MustBool("session", "cookie_secure")
|
||||
SessionConfig.EnableSetCookie = Cfg.MustBool("session", "enable_set_cookie", true)
|
||||
SessionConfig.Gclifetime = Cfg.MustInt64("session", "gc_interval_time", 86400)
|
||||
SessionConfig.Maxlifetime = Cfg.MustInt64("session", "session_life_time", 86400)
|
||||
SessionOptions = session.Options{}
|
||||
SessionOptions.Provider = Cfg.MustValueRange("session", "provider", "memory", []string{"memory", "file"})
|
||||
SessionOptions.ProviderConfig = strings.Trim(Cfg.MustValue("session", "provider_config"), "\" ")
|
||||
SessionOptions.CookieName = Cfg.MustValue("session", "cookie_name", "grafana_pro_sess")
|
||||
SessionOptions.CookiePath = AppSubUrl
|
||||
SessionOptions.Secure = Cfg.MustBool("session", "cookie_secure")
|
||||
SessionOptions.Gclifetime = Cfg.MustInt64("session", "gc_interval_time", 86400)
|
||||
SessionOptions.Maxlifetime = Cfg.MustInt64("session", "session_life_time", 86400)
|
||||
|
||||
if SessionProvider == "file" {
|
||||
os.MkdirAll(path.Dir(SessionConfig.ProviderConfig), os.ModePerm)
|
||||
if SessionOptions.Provider == "file" {
|
||||
os.MkdirAll(path.Dir(SessionOptions.ProviderConfig), os.ModePerm)
|
||||
}
|
||||
|
||||
log.Info("Session Service Enabled")
|
||||
|
Loading…
Reference in New Issue
Block a user