Skip to content

Commit

Permalink
all: properly implement regenerate session ID (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
unknwon committed May 2, 2024
1 parent 15e62f0 commit f19931a
Show file tree
Hide file tree
Showing 21 changed files with 175 additions and 96 deletions.
4 changes: 1 addition & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@ linters-settings:

linters:
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- nakedret
- gofmt
- rowserrcheck
- unconvert
- goimports
- unused
25 changes: 17 additions & 8 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ type fileStore struct {
nowFunc func() time.Time // The function to return the current time
lifetime time.Duration // The duration to have no access to a session before being recycled
rootDir string // The root directory of file session items stored on the local file system
encoder Encoder // The encoder to encode the session data before saving
decoder Decoder // The decoder to decode binary to session data after reading

encoder Encoder
decoder Decoder
idWriter IDWriter
}

// newFileStore returns a new file session store based on given configuration.
func newFileStore(cfg FileConfig) *fileStore {
func newFileStore(cfg FileConfig, idWriter IDWriter) *fileStore {
return &fileStore{
nowFunc: cfg.nowFunc,
lifetime: cfg.Lifetime,
rootDir: cfg.RootDir,
encoder: cfg.Encoder,
decoder: cfg.Decoder,
idWriter: idWriter,
}
}

Expand Down Expand Up @@ -70,7 +73,7 @@ func (s *fileStore) Read(_ context.Context, sid string) (Session, error) {
return nil, errors.Wrap(err, "create parent directory")
}

return NewBaseSession(sid, s.encoder), nil
return NewBaseSession(sid, s.encoder, s.idWriter), nil
}

// Discard existing data if it's expired
Expand All @@ -79,7 +82,7 @@ func (s *fileStore) Read(_ context.Context, sid string) (Session, error) {
return nil, errors.Wrap(err, "stat file")
}
if !fi.ModTime().Add(s.lifetime).After(s.nowFunc()) {
return NewBaseSession(sid, s.encoder), nil
return NewBaseSession(sid, s.encoder, s.idWriter), nil
}

binary, err := os.ReadFile(filename)
Expand All @@ -91,7 +94,7 @@ func (s *fileStore) Read(_ context.Context, sid string) (Session, error) {
if err != nil {
return nil, errors.Wrap(err, "decode")
}
return NewBaseSessionWithData(sid, s.encoder, data), nil
return NewBaseSessionWithData(sid, s.encoder, s.idWriter, data), nil
}

func (s *fileStore) Destroy(_ context.Context, sid string) error {
Expand Down Expand Up @@ -169,7 +172,7 @@ func (s *fileStore) GC(ctx context.Context) error {

// FileConfig contains options for the file session store.
type FileConfig struct {
// For tests only
// For tests only.
nowFunc func() time.Time

// Lifetime is the duration to have no access to a session before being
Expand All @@ -188,12 +191,18 @@ type FileConfig struct {
func FileIniter() Initer {
return func(ctx context.Context, args ...interface{}) (Store, error) {
var cfg *FileConfig
var idWriter IDWriter
for i := range args {
switch v := args[i].(type) {
case FileConfig:
cfg = &v
case IDWriter:
idWriter = v
}
}
if idWriter == nil {
return nil, errors.New("IDWriter not given")
}

if cfg == nil {
return nil, fmt.Errorf("config object with the type '%T' not found", FileConfig{})
Expand All @@ -214,6 +223,6 @@ func FileIniter() Initer {
cfg.Decoder = GobDecoder
}

return newFileStore(*cfg), nil
return newFileStore(*cfg, idWriter), nil
}
}
2 changes: 2 additions & 0 deletions file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func TestFileStore_GC(t *testing.T) {
RootDir: filepath.Join(os.TempDir(), "sessions"),
Lifetime: time.Second,
},
IDWriter(func(http.ResponseWriter, *http.Request, string) {}),
)
require.Nil(t, err)

Expand Down Expand Up @@ -137,6 +138,7 @@ func TestFileStore_Touch(t *testing.T) {
RootDir: filepath.Join(os.TempDir(), "sessions"),
Lifetime: time.Second,
},
IDWriter(func(http.ResponseWriter, *http.Request, string) {}),
)
require.Nil(t, err)

Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ go 1.18

require (
github.com/flamego/flamego v1.9.4
github.com/go-redis/redis/v8 v8.11.5
github.com/go-sql-driver/mysql v1.8.1
github.com/jackc/pgx/v5 v5.5.5
github.com/pkg/errors v0.9.1
github.com/redis/go-redis/v9 v9.5.1
github.com/stretchr/testify v1.9.0
go.mongodb.org/mongo-driver v1.14.0
modernc.org/sqlite v1.29.5
Expand All @@ -17,7 +17,7 @@ require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/alecthomas/participle/v2 v2.0.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/lipgloss v0.7.1 // indirect
github.com/charmbracelet/log v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down Expand Up @@ -49,7 +49,6 @@ require (
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
Expand Down
18 changes: 6 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmE
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
github.com/charmbracelet/log v0.2.3 h1:YVmBhJtpGL7nW/nlf5u+SEloU8XYljxozGzZpgwIvhs=
Expand All @@ -22,11 +24,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/flamego/flamego v1.9.4 h1:SNsooIfNa6ljQM1rBmfg4cFcXPIhQdG/uvNHqXxPvD8=
github.com/flamego/flamego v1.9.4/go.mod h1:2tAVbugA3fgX8xOBoqR2jmJSSvZDLBFGXTFCR5h5eAU=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
Expand Down Expand Up @@ -71,13 +70,12 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
Expand Down Expand Up @@ -110,8 +108,6 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
Expand Down Expand Up @@ -141,8 +137,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
2 changes: 1 addition & 1 deletion manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestIsValidSessionID(t *testing.T) {
}

func TestManager_startGC(t *testing.T) {
m := newManager(newMemoryStore(MemoryConfig{}))
m := newManager(newMemoryStore(MemoryConfig{}, nil))
stop := m.startGC(
context.Background(),
time.Minute,
Expand Down
21 changes: 16 additions & 5 deletions memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"context"
"sync"
"time"

"github.com/pkg/errors"
)

var _ Session = (*memorySession)(nil)
Expand All @@ -24,9 +26,9 @@ type memorySession struct {
}

// newMemorySession returns a new memory session with given session ID.
func newMemorySession(sid string) *memorySession {
func newMemorySession(sid string, idWriter IDWriter) *memorySession {
return &memorySession{
BaseSession: NewBaseSession(sid, nil),
BaseSession: NewBaseSession(sid, nil, idWriter),
}
}

Expand All @@ -52,15 +54,18 @@ type memoryStore struct {
lock sync.RWMutex // The mutex to guard accesses to the heap and index
heap []*memorySession // The heap to be managed by operations of heap.Interface
index map[string]*memorySession // The index to be managed by operations of heap.Interface

idWriter IDWriter
}

// newMemoryStore returns a new memory session store based on given
// configuration.
func newMemoryStore(cfg MemoryConfig) *memoryStore {
func newMemoryStore(cfg MemoryConfig, idWriter IDWriter) *memoryStore {
return &memoryStore{
nowFunc: cfg.nowFunc,
lifetime: cfg.Lifetime,
index: make(map[string]*memorySession),
idWriter: idWriter,
}
}

Expand Down Expand Up @@ -136,7 +141,7 @@ func (s *memoryStore) Read(_ context.Context, sid string) (Session, error) {
return sess, nil
}

sess = newMemorySession(sid)
sess = newMemorySession(sid, s.idWriter)
sess.SetLastAccessedAt(s.nowFunc())
heap.Push(s, sess)
return sess, nil
Expand Down Expand Up @@ -219,12 +224,18 @@ type MemoryConfig struct {
func MemoryIniter() Initer {
return func(_ context.Context, args ...interface{}) (Store, error) {
var cfg *MemoryConfig
var idWriter IDWriter
for i := range args {
switch v := args[i].(type) {
case MemoryConfig:
cfg = &v
case IDWriter:
idWriter = v
}
}
if idWriter == nil {
return nil, errors.New("IDWriter not given")
}

if cfg == nil {
cfg = &MemoryConfig{}
Expand All @@ -237,6 +248,6 @@ func MemoryIniter() Initer {
cfg.Lifetime = 3600 * time.Second
}

return newMemoryStore(*cfg), nil
return newMemoryStore(*cfg, idWriter), nil
}
}
2 changes: 2 additions & 0 deletions memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func TestMemoryStore_GC(t *testing.T) {
nowFunc: func() time.Time { return now },
Lifetime: time.Second,
},
nil,
)

sess1, err := store.Read(ctx, "1")
Expand Down Expand Up @@ -125,6 +126,7 @@ func TestMemoryStore_Touch(t *testing.T) {
nowFunc: func() time.Time { return now },
Lifetime: time.Second,
},
nil,
)

sess, err := store.Read(ctx, "1")
Expand Down
23 changes: 16 additions & 7 deletions mongo/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,22 @@ type mongoStore struct {
lifetime time.Duration // The duration to have access to a session before being recycled
db *mongo.Database // The database connection
collection string // The database collection for storing session data
encoder session.Encoder // The encoder to encode the session data before saving
decoder session.Decoder // The decoder to decode binary to session data after reading

encoder session.Encoder
decoder session.Decoder
idWriter session.IDWriter
}

// newMongoStore returns a new MongoDB session store based on given configuration.
func newMongoStore(cfg Config) *mongoStore {
func newMongoStore(cfg Config, idWriter session.IDWriter) *mongoStore {
return &mongoStore{
nowFunc: cfg.nowFunc,
lifetime: cfg.Lifetime,
db: cfg.db,
collection: cfg.Collection,
encoder: cfg.Encoder,
decoder: cfg.Decoder,
idWriter: idWriter,
}
}

Expand All @@ -63,19 +66,19 @@ func (s *mongoStore) Read(ctx context.Context, sid string) (session.Session, err

// Discard existing data if it's expired
if !s.nowFunc().Before(expiredAt.Time().Add(s.lifetime)) {
return session.NewBaseSession(sid, s.encoder), nil
return session.NewBaseSession(sid, s.encoder, s.idWriter), nil
}

data, err := s.decoder(binary.Data)
if err != nil {
return nil, errors.Wrap(err, "decode")
}
return session.NewBaseSessionWithData(sid, s.encoder, data), nil
return session.NewBaseSessionWithData(sid, s.encoder, s.idWriter, data), nil
} else if err != mongo.ErrNoDocuments {
return nil, errors.Wrap(err, "find")
}

return session.NewBaseSession(sid, s.encoder), nil
return session.NewBaseSession(sid, s.encoder, s.idWriter), nil
}

func (s *mongoStore) Destroy(ctx context.Context, sid string) error {
Expand Down Expand Up @@ -157,12 +160,18 @@ type Config struct {
func Initer() session.Initer {
return func(ctx context.Context, args ...interface{}) (session.Store, error) {
var cfg *Config
var idWriter session.IDWriter
for i := range args {
switch v := args[i].(type) {
case Config:
cfg = &v
case session.IDWriter:
idWriter = v
}
}
if idWriter == nil {
return nil, errors.New("IDWriter not given")
}

if cfg == nil {
return nil, fmt.Errorf("config object with the type '%T' not found", Config{})
Expand Down Expand Up @@ -194,6 +203,6 @@ func Initer() session.Initer {
cfg.Decoder = session.GobDecoder
}

return newMongoStore(*cfg), nil
return newMongoStore(*cfg, idWriter), nil
}
}

0 comments on commit f19931a

Please sign in to comment.