This repository has been archived by the owner on May 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathsession.go
108 lines (95 loc) · 2.75 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
package webwire
import (
cryptoRand "crypto/rand"
"encoding/base64"
"fmt"
"time"
)
// generateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func generateRandomBytes(length uint32) (bytes []byte, err error) {
bytes = make([]byte, length)
_, err = cryptoRand.Read(bytes)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return bytes, nil
}
// generateSessionKey returns a URL-safe, base64 encoded
// securely generated random string.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func generateSessionKey() string {
bytes, err := generateRandomBytes(48)
if err != nil {
panic(fmt.Errorf("Could not generate a session key"))
}
return base64.URLEncoding.EncodeToString(bytes)
}
// JSONEncodedSession represents a JSON encoded session object.
// This structure is used during session restoration for unmarshalling
// TODO: move to internal shared package
type JSONEncodedSession struct {
Key string `json:"k"`
Creation time.Time `json:"c"`
LastLookup time.Time `json:"l"`
Info map[string]interface{} `json:"i,omitempty"`
}
// Session represents a session object.
// If the key is empty the session is invalid.
// Info can contain arbitrary attached data
type Session struct {
Key string
Creation time.Time
LastLookup time.Time
Info SessionInfo
}
// Clone returns an exact copy of the session object
func (s *Session) Clone() *Session {
if s == nil {
return nil
}
var info SessionInfo
if s.Info != nil {
info = s.Info.Copy()
}
return &Session{
Key: s.Key,
Creation: s.Creation,
LastLookup: s.LastLookup,
Info: info,
}
}
// NewSession generates a new session object
// generating a cryptographically random secure key
func NewSession(info SessionInfo, generator func() string) Session {
key := generator()
if len(key) < 1 {
panic(fmt.Errorf(
"Invalid session key returned by the session key generator (empty)",
))
}
timeNow := time.Now()
return Session{
key,
timeNow,
timeNow,
info,
}
}
// DefaultSessionKeyGenerator implements
// the webwire.SessionKeyGenerator interface
type DefaultSessionKeyGenerator struct{}
// NewDefaultSessionKeyGenerator constructs a new default
// session key generator implementation
func NewDefaultSessionKeyGenerator() SessionKeyGenerator {
return &DefaultSessionKeyGenerator{}
}
// Generate implements the webwire.Sessio
func (gen *DefaultSessionKeyGenerator) Generate() string {
return generateSessionKey()
}