-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathsession.go
147 lines (125 loc) · 3.39 KB
/
session.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package tgw
import (
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"net/http"
"sync"
"time"
)
type SessionStoreInterface interface {
Get(sid string, key string, val interface{}) error
Set(sid string, key string, val interface{}) error
Clear(sid string, key string)
SetString(sid string, key string, val string) error
GetString(sid string, key string) (string, error)
}
type SessionInterface interface {
Get(key string, val interface{}) error
Set(key string, val interface{}) error
SetString(key string, val string) error
GetString(key string) (string, error)
Clear(key string)
Id() string
}
var (
SESSION_NAME = "TGW_SESSION_ID"
sidMux = sync.RWMutex{}
)
//==================================================
type SimpleSession struct {
id string
rw http.ResponseWriter
req *http.Request
store SessionStoreInterface
}
// Options --------------------------------------------------------------------
// Options stores configuration for a session or session store.
//
// Fields are a subset of http.Cookie fields.
type Options struct {
Path string
Domain string
// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'.
// MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int
Secure bool
HttpOnly bool
}
var DefaultSessionOptions = &Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: true,
}
func NewSimpleSession(rw http.ResponseWriter, req *http.Request, store SessionStoreInterface) (session *SimpleSession) {
session = &SimpleSession{
rw: rw,
req: req,
store: store,
}
coki, err := req.Cookie(SESSION_NAME)
if err == nil && coki != nil {
session.id = coki.Value
} else {
session.id = getSid()
session.Flush()
// (*session.value)[session.id] = make(d)
}
return
}
func getSid() string {
sidMux.Lock()
defer sidMux.Unlock()
now := time.Now().UnixNano()
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(now))
hash := sha1.New()
hash.Write(b)
return base64.URLEncoding.EncodeToString(hash.Sum(nil))
}
// NewCookie returns an http.Cookie with the options set. It also sets
// the Expires field calculated based on the MaxAge value, for Internet
// Explorer compatibility.
func NewCookie(name, value string) *http.Cookie {
options := DefaultSessionOptions
cookie := &http.Cookie{
Name: name,
Value: value,
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
}
if options.MaxAge > 0 {
d := time.Duration(options.MaxAge) * time.Second
cookie.Expires = time.Now().Add(d)
} else if options.MaxAge < 0 {
// Set it to the past to expire now.
cookie.Expires = time.Unix(1, 0)
}
return cookie
}
func (s *SimpleSession) Id() string {
return s.id
}
func (s *SimpleSession) Clear(key string) {
s.store.Clear(s.id, key)
}
func (s *SimpleSession) Get(key string, val interface{}) (err error) {
return s.store.Get(s.id, key, val)
}
func (s *SimpleSession) Set(key string, val interface{}) (err error) {
return s.store.Set(s.id, key, val)
}
func (s *SimpleSession) SetString(key string, val string) (err error) {
return s.store.SetString(s.id, key, val)
}
func (s *SimpleSession) GetString(key string) (string, error) {
return s.store.GetString(s.id, key)
}
func (s *SimpleSession) Flush() {
coki := NewCookie(SESSION_NAME, s.id)
http.SetCookie(s.rw, coki)
}