
templates.plugins.spincast-session.spincast-session.html Maven / Gradle / Ivy
Show all versions of spincast-website Show documentation
{% extends "../../layout.html" %}
{% block sectionClasses %}plugins hasBreadCrumb plugins-spincast-session{% endblock %}
{% block meta_title %}Plugins - Spincast Session{% endblock %}
{% block meta_description %}Spincast Session plugin - manage sessions for the application users{% endblock %}
{% block scripts %}
{% endblock %}
{% block body %}
Overview
This plugin provides the logic required to manage sessions associated to the users of your application.
In summary, a session
is an object containing informations about a particular user.
Those informations can be saved in the application and later associated back to the user when
he performs a new request. The default mechanism used to be able to bind such informations
to a specific user is to save a "session id"
in a cookie, on the user.
This plugin is mostly useful for your application specific needs, but it can
also be used by other plugins that need to keep informations about users.
For example, the Spincast Forms Protection plugin
uses the sessions provided by this plugin to store "CSRF
" tokens required to
protect forms, in your application.
Usage
Getting the session of the current visitor
Once the plugin and its associated filters have been properly installed,
you simply need to use the
SpincastSessionManager
to manage sessions.
The most important method provided by this manager is getCurrentSession()
, which gives you access
to the session of the current visitor:
{% verbatim %}
public class MyClass {
private final SpincastSessionManager spincastSessionManager;
@Inject
public MyClass(SpincastSessionManager spincastSessionManager) {
this.spincastSessionManager = spincastSessionManager;
}
protected SpincastSessionManager getSpincastSessionManager() {
return this.spincastSessionManager;
}
public void myRouteHandler(AppRequestContext context) {
SpincastSession currentSession = getSpincastSessionManager().getCurrentSession();
Long userId = currentSession.getAttributes().getLong("userId");
if(userId != null) {
User user = getUserService().getUser(userId);
}
// ....
}
}
{% endverbatim %}
Explanation :
-
15 : Gets the session of the current
visitor.
-
16 : Gets an information
you associated with this session (here a "
user id
").
The informations saved in the session are
named "attributes
" and they are implemented using a
JsonObject.
Note that once the plugin has been installed properly, a session returned by
SpincastSessionManager#getCurrentSession()
is never null
! If no session already exists for the current visitor, a new one is automatically created.
Storing and retrieving session attributes
Since the attributes of a session are accessible on a JsonObject object,
getting them in a typed way is really easy. Adding new ones too. You simply call
getAttributes()
on the session to have access to them.
Note that an after
filter will
take care of saving a session that has been modified during a request, you don't have to do it
manually!
Getting the current session using an add-on
If you use sessions a lot in your application, we suggest you add a
"session()
" add-on
to your custom Request Context!
By adding a new "session()
" method pointing to
SpincastSessionManager#getCurrentSession(),
you get easy access to the current session in your routes handlers:
{% verbatim %}
public void myRouteHandler(AppRequestContext context) {
Long userId = context.session().getAttributes().getLong("userId");
if(userId != null) {
User user = getUserService().getUser(userId);
}
// ....
}
{% endverbatim %}
Dependencies
The Spincast Session plugin depends on the Spincast Scheduled Tasks plugin, a plugin which is not
provided by default by the spincast-default
package. This dependency plugin will be automatically installed,
you don't need to install it by yourself in your application (but you can).
Just don't be surprised if you see transitive dependencies being added to your application!
It is always a good idea to read the documentation of the plugins that are
automatically added. You
may want to modify some of their default configurations!
Installation
This plugin work out-of-the-box, but we recommend some of the parts to be tweaked! For example,
the default SpincastSessionRepository
implementation, used to store the sessions, is based on cookies, and you may want a more robust solution.
But let's start with step one...
Installing the plugin itself
1.
Add this Maven artifact to your project:
<dependency>
<groupId>org.spincast</groupId>
<artifactId>spincast-plugins-session</artifactId>
<version>{{spincast.spincastCurrrentVersion}}</version>
</dependency>
2.
Add an instance of the SpincastSessionPlugin
plugin to your Spincast Bootstrapper:
{% verbatim %}
Spincast.configure()
.plugin(new SpincastSessionPlugin())
// ...
{% endverbatim %}
Session filters
Two filters are required for this plugin to work properly.
-
The first filter, a before filter, makes sure the session is loaded and
available through your application.
-
The second filter, an after filter, makes sure a modified session is
saved at the end of a request.
By default, those filters are automatically added by the plugin! You can disable this by
setting isAutoAddSessionFilters()
to false
.
The default positions used to add those filters are -100
and 100
respectively. If you let the plugin bind the filters, you can still modify those positions
by using the getAutoAddedFilterBeforePosition()
and getAutoAddedFilterAfterPosition()
configurations.
To bind the filters by yourself (if you need full control), disable isAutoAddSessionFilters()
and then:
{% verbatim %}
@Inject
SpincastSessionFilter spincastSessionFilter;
// "Before" filter
router.ALL()
.id(SpincastSessionFilter.ROUTE_ID_BEFORE_FILTER)
.pos(-1000)
.skipResourcesRequests()
.handle(spincastSessionFilter::before);
// "After" filter
router.ALL()
.id(SpincastSessionFilter.ROUTE_ID_AFTER_FILTER)
.pos(200)
.skipResourcesRequests()
.handle(spincastSessionFilter::after);
{% endverbatim %}
By using the provided ids ("SpincastSessionFilter.ROUTE_ID_BEFORE_FILTER
" and
"SpincastSessionFilter.ROUTE_ID_AFTER_FILTER
") you make sure the filters will
only be added by you, since the same id can only be used once (otherwise an exception
is thrown when the application starts).
In a typical application, a custom filter that is often created and added is one to retrieve a logged in
User
from the database and add it to the request's variables,
so the user is easily accessible to the application's code.
Such UserFilter
would probably need to be added at a position after the
spincastSessionFilter::before
filter! Indeed,
the UserFilter
would use the session of the current visitor to determine
if he is a logged in user or not and, if so, what is his "userId
" (an attribute
saved in the session!). This is an example of why being able to modify the positions of
filters may be important.
Repository implementation
This plugin is totally agnostic on how the sessions are actually persisted. It is the
implementation of SpincastSessionRepository
that controls how the sessions are actually saved. The default implementation is
SpincastSessionRepositoryDefault
which saved the sessions in a cookie on the users.
Even if a default repository is provided, we recommend that you do bind a custom repository using a real database!
The default repository, that uses cookies,
is somewhat limited. The number of characters that can be stored in a cookie
is indeed limited...
There are four methods to implement in a custom repository:
-
void saveSession(SpincastSession session)
This method will be called by the plugin when a current session needs to be
saved to the database.
Note that the modification date
of the session to save is
already updated when this method is called! You don't have to update it by yourself,
manually or using a database trigger.
-
SpincastSession getSession(String sessionId)
This method will be called by the plugin to retrieve a session saved in
the database.
It must return a SpincastSession
instance, or null
if it's not found.
-
void deleteSession(String sessionId)
This method will be called by the plugin to delete a session.
If no session with this sessionId
exists, nothing is done.
-
void deleteOldInactiveSession(int sessionMaxInactiveMinutes)
This method will be called by the plugin to delete sessions that have been inactive
for more than sessionMaxInactiveMinutes
minutes.
Your query/code must use the modification date
of the saved sessions to
determine which sessions to delete.
SQL/JDBC example
Here's an example of an SQL script (targeting PostgreSQL
) to create a
"sessions
" table. You will probably have to adjust this query
for your own database! Or even to use something totally different if you
are not using a relational database.
{% verbatim %}
CREATE TABLE sessions (
session_id VARCHAR(36) PRIMARY KEY,
attributes_serialized TEXT,
creation_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),
modification_date TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
{% endverbatim %}
To serialize and deserialize the session's attributes
, you can
simply use the JsonObject's
toJsonString()
and JsonManager's fromString():
{% verbatim %}
Saving a session to the database:
InsertStatement stm = jdbc().statements().createInsertStatement(connection);
stm.sql("INSERT INTO sessions( // ...
stm.setString("attributes_serialized", session.getAttributes().toJsonString());
{% endverbatim %}
{% verbatim %}
Retrieving a session from the database:
SelectStatement stm = jdbc().statements().createSelectStatement(connection);
stm.sql("SELECT session_id, // ...
JsonObject attributes =
getJsonManager().fromString(rs.getString("attributes_serialized"));
SpincastSession session =
getSpincastSessionManager().createSession(rs.getString("session_id"),
rs.getInstant("creation_date"),
rs.getInstant("modification_date"),
attributes);
{% endverbatim %}
Configurations
The configuration interface for this plugin is
SpincastSessionConfig.
To change the default configurations, you can bind an implementation of
that interface, extending the default
SpincastSessionConfigDefault
implementation if you don't want to start from scratch.
Options:
-
int getSessionMaxInactiveMinutes()
The number of minutes an existing session can stay inactive (not being used) before it is
garbage collected by the cleanup scheduled task.
If a user with a saved session doesn't visit your application for this long, his session
will be lost.
Defaults to 10080
minutes (7 days).
-
int getDeleteOldSessionsScheduledTaskRunEveryNbrMinutes()
How often should the scheduled task to delete the old sessions (by calling the
deleteOldInactiveSession() method that you implemented) run? This
configuration returns the number of minutes between two launches of the cleanup scheduled task.
Defaults to 30
minutes.
-
int getUpdateNotDirtySessionPeriodInSeconds()
The after
filter provided by the plugin (and that you added to your router!)
doesn't save a session that is not dirty on each and every request, simply to update its modification date
...
This wouldn't be very efficient. The filter rather saves a session that is not dirty only once during the period
specified by this configuration.
Important! This period must be shorter than the period
specified by getSessionMaxInactiveMinutes()
or otherwise some active sessions may be deleted!
Defaults to 300
seconds (5 minutes).
-
String getSessionIdCookieName()
The name of the cookie that is used to store the session id, on the user.
Defaults to "spincast_sid
".
-
String getDefaultCookieRepositoryCookieName()
When the default repository
is used, this will be the name of the cookie used to store a session, on the user.
Defaults to "spincast_session
".
-
boolean isAutoAddSessionFilters()
Should the required before and after
filters be added automatically? If false
, you will have to add them by
yourself.
Defaults to true
.
-
int getAutoAddedFilterBeforePosition()
When the session filters are added automatically,
this will be the position of the before
filter.
Defaults to -100
.
-
int getAutoAddedFilterAfterPosition()
When the session filters are added automatically,
this will be the position of the after
filter.
Defaults to 100
.
{% endblock %}