Session ManagementHTTP session related functonality is handled by a combination of the
SessionManagementFilter and the
SessionAuthenticationStrategy interface, which the filter
delegates to. Typical usage includes session-fixation protection attack prevention,
detection of session timeouts and restrictions on how many sessions an authenticated user
may have open concurrently.SessionManagementFilterThe SessionManagementFilter checks the contents of the
SecurityContextRepository against the current contents of
the SecurityContextHolder to determine whether a user has been
authenticated during the current request, typically by a non-interactive authentication
mechanism, such as pre-authentication or remember-me Authentication by mechanisms which perform a redirect after authenticating (such
as form-login) will not be detected by
SessionManagementFilter, as the filter will not be invoked
during the authenticating request. Session-management functionality has to be
handled separately in these cases. . If the repository contains a security context, the filter does nothing. If
it doesn't, and the thread-local SecurityContext contains
a (non-anonymous) Authentication object, the filter
assumes they have been authenticated by a previous filter in the stack. It will then
invoke the configured
SessionAuthenticationStrategy.If the user is not currently authenticated, the filter will check whether an invalid
session ID has been requested (because of a timeout, for example) and will invoke the configured
InvalidSessionStrategy, if one is set. The most common behaviour
is just to redirect to a fixed URL and this is encapsulated in the standard implementation
SimpleRedirectInvalidSessionStrategy. The latter is also used
when configuring an invalid session URL through the namespace,
as described earlier.SessionAuthenticationStrategySessionAuthenticationStrategy is used by both
SessionManagementFilter and
AbstractAuthenticationProcessingFilter, so if you are using a
customized form-login class, for example, you will need to inject it into both of these.
In this case, a typical configuration, combining the namespace and custom beans might
look like this:
...
]]>
Note that the use of the default, SessionFixationProtectionStrategy
may cause issues if you are storing beans in the session which implement
HttpSessionBindingListener, including Spring session-scoped
beans. See the Javadoc for this class for more information.
Concurrency ControlSpring Security is able to prevent a principal from concurrently authenticating to the
same application more than a specified number of times. Many ISVs take advantage of this
to enforce licensing, whilst network administrators like this feature because it helps
prevent people from sharing login names. You can, for example, stop user
Batman from logging onto the web application from two different sessions.
You can either expire their previous login or you can report an error when they try to
log in again, preventing the second login. Note that if you are using the second
approach, a user who has not explicitly logged out (but who has just closed their
browser, for example) will not be able to log in again until their original session
expires.Concurrency control is supported by the namespace, so please check the earlier
namespace chapter for the simplest configuration. Sometimes you need to customize things
though. The implementation uses a specialized version of
SessionAuthenticationStrategy, called
ConcurrentSessionControlAuthenticationStrategy. Previously the concurrent authentication check was made by the
ProviderManager, which could be injected with a
ConcurrentSessionController. The latter would check if the user
was attempting to exceed the number of permitted sessions. However, this approach
required that an HTTP session be created in advance, which is undesirable. In Spring
Security 3, the user is first authenticated by the
AuthenticationManager and once they are successfully
authenticated, a session is created and the check is made whether they are allowed
to have another session open.To use concurrent session support, you'll need to add the following to
web.xml:
org.springframework.security.web.session.HttpSessionEventPublisher
]]>
In addition, you will need to add the ConcurrentSessionFilter to
your FilterChainProxy. The
ConcurrentSessionFilter requires two properties,
sessionRegistry, which generally points to an instance of
SessionRegistryImpl, and expiredUrl, which
points to the page to display when a session has expired. A configuration using the
namespace to create the FilterChainProxy and other default beans
might look like this:
]]>
Adding the listener to web.xml causes an
ApplicationEvent to be published to the Spring
ApplicationContext every time a HttpSession
commences or terminates. This is critical, as it allows the
SessionRegistryImpl to be notified when a session ends. Without
it, a user will never be able to log back in again once they have exceeded their session
allowance, even if they log out of another session or it times out.Querying the SessionRegistry for currently authenticated
users and their sessions
Setting up concurrency-control, either through the namespace or using plain beans has the
useful side effect of providing you with a reference to the SessionRegistry
which you can use directly within your application, so even if you don't want to restrict the
number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can
set the maximumSession property to -1 to allow unlimited sessions. If
you're using the namespace, you can set an alias for the internally-created
SessionRegistry using the session-registry-alias
attribute, providing a reference which you can inject into your own beans.
The getAllPrincipals()
method supplies you with a list of the currently authenticated users. You can list a user's
sessions by calling the getAllSessions(Object principal, boolean includeExpiredSessions) method,
which returns a list of SessionInformation objects. You can also
expire a user's session by calling expireNow() on a
SessionInformation instance. When the user returns to the application, they
will be prevented from proceeding. You may find these methods useful in an administration
application, for example. Have a look at the Javadoc for more information.