-
-
Notifications
You must be signed in to change notification settings - Fork 9
SessionStorage
The default of the sessions
package is to keep session data in RAM. This is obviously not desired in production so you will want to connect it to your own session database. This package does not make many assumptions about the database's technology so you may use file based storage, an SQL database, or no-SQL data stores.
You only need to change one package variable: sessions.Persistence
. It is of the type PersistenceLayer
(Godoc), an interface with six functions which we describe below. If you intend to implement all of them, it makes sense to create your own type which implements PersistenceLayer
. Sometimes only a few of the functions need to be implemented. In that case, a better option is to instantiate the ExtendablePersistenceLayer
struct (Godoc). The fields of this struct are six functions which may be nil
. ExtendablePersistenceLayer
implements PersistenceLayer
in such a way that it calls its respective function if the the field is not nil
or does nothing if the field is nil
.
Example:
sessions.Persistence = sessions.ExtendablePersistenceLayer{
LoadSessionFunc: func(id string) (*sessions.Session, error) {
// ... Generate a session ...
return session, nil
},
}
For the following sections, refer also to the Godoc documentation.
LoadSession()
retrieves a Session
object for a given session ID. The function must be thread-safe. It is very common that the function is called for session IDs for which no sessions exist yet. This is not an error. The function then simply returns a nil
object (and a nil
error).
The Session
type provides a number of ways to recover Session
objects from byte slices or strings. It implements the Gob Decoder as well as the JSON Unmarshaler interfaces. Storing sessions as JSON has the advantage that the string representation is human-readable. However, the lack of types in the JSON representation leads to the conversion not being bijective. That is, you may not get the exact same Go object when converting to JSON and back. This will not matter if you don't use session storage and if user IDs are strings (integers will convert back to float64). Therefore, it is recommended to use the gob
package to store and retrieve Session
objects.
Example:
func LoadSession(id string) (*sessions.Session, error) {
// ... load session bytes b from database ...
r := bytes.NewReader(b)
decoder := gob.NewDecoder(r)
var session sessions.Session
if err := decoder.Decode(&session); err != nil {
return nil, err
}
return &session, nil
}
SaveSession()
stores the session in your session database. Your implementation should insert the session if it doesn't exist yet in your database and update it to the provided session object if it already exists. Just as with LoadSession()
, we can use JSON or Gob to encode the Session
object but the same restrictions apply for JSON.
DeleteSession()
deletes a session with the given session ID from your session database. This ensures that sessions are not reused after they expire.
Because the sessions
package always checks if a session is still valid, theoretically, you could choose not to implement DeleteSession()
. But as a precaution, it is recommended. (Also, if you use the Session.Destroy()
function, it may not work as expected if DeleteSession()
does not do anything.)
Note that the sessions
package does not purge expired sessions from your database that have not been accessed. It is recommended that you schedule a regular session cleanup script that deletes those sessions from your database that have expired.
The UserSessions()
function returns all session IDs of a specific user. Users are identified by a user ID (which may be of any type as long as it is ==
comparable). Sessions have a field for user IDs, used to attach a user to it (logging in) or detaching them (logging out). Sometimes, it is desirable to log a user out of all of their sessions. For this to work, the UserSessions()
should identify all sessions a user owns.
If you don't work with the sessions.User
type or don't need the functionality to log all users out, you may choose not to implement this function.
LoadUser()
loads a sessions.User
object from the database given a user ID. A session itself only stores a user ID but can return a user object, that's where this function is needed.
If you don't access a session's user, you don't need to implement this function.
This is work in progress and may change or be removed in the future.