@@ -45,7 +45,7 @@ func (s *Session) init() error {
45
45
// Retrieve stored session data from storage.
46
46
if s .manager .storage != nil {
47
47
s .data , err = s .manager .storage .GetSession (s .ctx , s .id , s .manager .GetTTL ())
48
- if err != nil && err != ErrorDisabled {
48
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
49
49
intlog .Errorf (s .ctx , `session restoring failed for id "%s": %+v` , s .id , err )
50
50
return err
51
51
}
@@ -59,7 +59,7 @@ func (s *Session) init() error {
59
59
} else {
60
60
// Use default session id creating function of storage.
61
61
s .id , err = s .manager .storage .New (s .ctx , s .manager .ttl )
62
- if err != nil && err != ErrorDisabled {
62
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
63
63
intlog .Errorf (s .ctx , "create session id failed: %+v" , err )
64
64
return err
65
65
}
@@ -89,12 +89,12 @@ func (s *Session) Close() error {
89
89
size := s .data .Size ()
90
90
if s .dirty {
91
91
err := s .manager .storage .SetSession (s .ctx , s .id , s .data , s .manager .ttl )
92
- if err != nil && err != ErrorDisabled {
92
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
93
93
return err
94
94
}
95
95
} else if size > 0 {
96
96
err := s .manager .storage .UpdateTTL (s .ctx , s .id , s .manager .ttl )
97
- if err != nil && err != ErrorDisabled {
97
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
98
98
return err
99
99
}
100
100
}
@@ -108,11 +108,10 @@ func (s *Session) Set(key string, value interface{}) (err error) {
108
108
return err
109
109
}
110
110
if err = s .manager .storage .Set (s .ctx , s .id , key , value , s .manager .ttl ); err != nil {
111
- if err == ErrorDisabled {
112
- s .data .Set (key , value )
113
- } else {
111
+ if ! gerror .Is (err , ErrorDisabled ) {
114
112
return err
115
113
}
114
+ s .data .Set (key , value )
116
115
}
117
116
s .dirty = true
118
117
return nil
@@ -124,11 +123,10 @@ func (s *Session) SetMap(data map[string]interface{}) (err error) {
124
123
return err
125
124
}
126
125
if err = s .manager .storage .SetMap (s .ctx , s .id , data , s .manager .ttl ); err != nil {
127
- if err == ErrorDisabled {
128
- s .data .Sets (data )
129
- } else {
126
+ if ! gerror .Is (err , ErrorDisabled ) {
130
127
return err
131
128
}
129
+ s .data .Sets (data )
132
130
}
133
131
s .dirty = true
134
132
return nil
@@ -144,11 +142,10 @@ func (s *Session) Remove(keys ...string) (err error) {
144
142
}
145
143
for _ , key := range keys {
146
144
if err = s .manager .storage .Remove (s .ctx , s .id , key ); err != nil {
147
- if err == ErrorDisabled {
148
- s .data .Remove (key )
149
- } else {
145
+ if ! gerror .Is (err , ErrorDisabled ) {
150
146
return err
151
147
}
148
+ s .data .Remove (key )
152
149
}
153
150
}
154
151
s .dirty = true
@@ -164,7 +161,7 @@ func (s *Session) RemoveAll() (err error) {
164
161
return err
165
162
}
166
163
if err = s .manager .storage .RemoveAll (s .ctx , s .id ); err != nil {
167
- if err != ErrorDisabled {
164
+ if ! gerror . Is ( err , ErrorDisabled ) {
168
165
return err
169
166
}
170
167
}
@@ -215,7 +212,7 @@ func (s *Session) Data() (sessionData map[string]interface{}, err error) {
215
212
return nil , err
216
213
}
217
214
sessionData , err = s .manager .storage .Data (s .ctx , s .id )
218
- if err != nil && err != ErrorDisabled {
215
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
219
216
intlog .Errorf (s .ctx , `%+v` , err )
220
217
}
221
218
if sessionData != nil {
@@ -233,7 +230,7 @@ func (s *Session) Size() (size int, err error) {
233
230
return 0 , err
234
231
}
235
232
size , err = s .manager .storage .GetSize (s .ctx , s .id )
236
- if err != nil && err != ErrorDisabled {
233
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
237
234
intlog .Errorf (s .ctx , `%+v` , err )
238
235
}
239
236
if size > 0 {
@@ -273,7 +270,7 @@ func (s *Session) Get(key string, def ...interface{}) (value *gvar.Var, err erro
273
270
return nil , err
274
271
}
275
272
v , err := s .manager .storage .Get (s .ctx , s .id , key )
276
- if err != nil && err != ErrorDisabled {
273
+ if err != nil && ! gerror . Is ( err , ErrorDisabled ) {
277
274
intlog .Errorf (s .ctx , `%+v` , err )
278
275
return nil , err
279
276
}
@@ -357,3 +354,60 @@ func (s *Session) MustRemove(keys ...string) {
357
354
panic (err )
358
355
}
359
356
}
357
+
358
+ // RegenerateId regenerates a new session id for current session.
359
+ // It keeps the session data and updates the session id with a new one.
360
+ // This is commonly used to prevent session fixation attacks and increase security.
361
+ //
362
+ // The parameter `deleteOld` specifies whether to delete the old session data:
363
+ // - If true: the old session data will be deleted immediately
364
+ // - If false: the old session data will be kept and expire according to its TTL
365
+ func (s * Session ) RegenerateId (deleteOld bool ) (newId string , err error ) {
366
+ if err = s .init (); err != nil {
367
+ return "" , err
368
+ }
369
+
370
+ // Generate new session id
371
+ if s .idFunc != nil {
372
+ newId = s .idFunc (s .manager .ttl )
373
+ } else {
374
+ newId , err = s .manager .storage .New (s .ctx , s .manager .ttl )
375
+ if err != nil && ! gerror .Is (err , ErrorDisabled ) {
376
+ return "" , err
377
+ }
378
+ if newId == "" {
379
+ newId = NewSessionId ()
380
+ }
381
+ }
382
+
383
+ // If using storage, need to copy data to new id
384
+ if s .manager .storage != nil {
385
+ if err = s .manager .storage .SetSession (s .ctx , newId , s .data , s .manager .ttl ); err != nil {
386
+ if ! gerror .Is (err , ErrorDisabled ) {
387
+ return "" , err
388
+ }
389
+ }
390
+ // Delete old session data if requested
391
+ if deleteOld {
392
+ if err = s .manager .storage .RemoveAll (s .ctx , s .id ); err != nil {
393
+ if ! gerror .Is (err , ErrorDisabled ) {
394
+ return "" , err
395
+ }
396
+ }
397
+ }
398
+ }
399
+
400
+ // Update session id
401
+ s .id = newId
402
+ s .dirty = true
403
+ return newId , nil
404
+ }
405
+
406
+ // MustRegenerateId performs as function RegenerateId, but it panics if any error occurs.
407
+ func (s * Session ) MustRegenerateId (deleteOld bool ) string {
408
+ newId , err := s .RegenerateId (deleteOld )
409
+ if err != nil {
410
+ panic (err )
411
+ }
412
+ return newId
413
+ }
0 commit comments