Package net.shibboleth.idp.session.impl

# Class StorageBackedSessionManager

java.lang.Object
net.shibboleth.shared.component.AbstractInitializableComponent
net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent
net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent
net.shibboleth.idp.session.impl.StorageBackedSessionManager

All Implemented Interfaces:
  `SessionManager`, `SessionResolver`, `Component`, `DestructableComponent`, `IdentifiableComponent`, `IdentifiedComponent`, `InitializableComponent`, `Resolver<IdPSession,CriteriaSet>`

public class StorageBackedSessionManager extends AbstractIdentifiableInitializableComponent implements SessionManager, SessionResolver
Implementation of `SessionManager` and `SessionResolver` interfaces that relies on a `StorageService` for persistence and lifecycle management of data.

The storage layout here is to store most data in a context named for the session ID. Within that context, the `IdPSession` record lives under a key called "_session", with an expiration based on the session timeout value plus a configurable amount of "slop" to prevent premature disappearance in case of logout.

Each `AuthenticationResult` is stored in a record keyed by the flow ID. The expiration is set based on the underlying flow's timeout.

Each `SPSession` is stored in a record keyed by the service ID. The expiration is set based on the SPSession's own expiration plus the "slop" value.

For cross-referencing, lists of flow and service IDs are tracked within the "_session" record, so adding either requires an update to that record plus the creation of a new one. Post-creation, there are no updates to the AuthenticationResult or SPSession records, but the expiration of the result records can be updated to reflect activity updates.

When a SPSession is added, it may expose an optional secondary "key". If set, this is a signal to add a secondary lookup of the SPSession. This is a record containing a list of relevant IdPSession IDs stored under a context/key pair consisting of the Service ID and the exposed secondary key from the object. The expiration of this record is set based on the larger of the current list expiration, if any, and the expiration of the SPSession plus the configured slop value. In other words, the lifetime of the index record is pushed out as far as needed to avoid premature expiration while any of the SPSessions producing it remain around.

The primary purpose of the secondary list is SAML logout, and is an optional feature that can be disabled. In the case of a SAML 2 session, the secondary key is some form of the NameID issued to the service.

## Nested Class Summary

Nested Classes
Modifier and Type
Class
Description
`static class`
`StorageBackedSessionManager.DefaultConsistentAddressConditionFactory`
Simplifies Spring wiring of a true/false condition for the consistentAddress feature.

## Field Summary

Fields
Modifier and Type
Field
Description
`private BiPredicate<String,String>`
`consistentAddressCondition`
Indicates how bound session addresses and client addresses are compared.
`private CookieManager`
`cookieManager`
Manages creation of cookies.
`private String`
`cookieName`
Name of cookie used to track sessions.
`protected static final String`
`DEFAULT_COOKIE_NAME`
Default cookie name for session tracking.
`private final Map<String,AuthenticationFlowDescriptor>`
`flowDescriptorMap`
Flows that could potentially be used to authenticate the user.
`private NonnullSupplier<HttpServletRequest>`
`httpRequestSupplier`
Servlet request to read from.
`private IdentifierGenerationStrategy`
`idGenerator`
Generator for XML ID attribute values.
`private final org.slf4j.Logger`
`log`
Class logger.
`private boolean`
`maskStorageFailure`
Indicates that storage service failures should be masked as much as possible.
`private boolean`
`secondaryServiceIndex`
Indicates whether to secondary-index SPSessions.
`private final StorageBackedIdPSessionSerializer`
`serializer`
Serializer for sessions.
`static final String`
`SESSION_PRIMARY_KEY`
Storage key of primary session records.
`private Duration`
`sessionSlop`
Amount of time to defer expiration of records for better handling of logout.
`private Duration`
`sessionTimeout`
Inactivity timeout for sessions.
`private SPSessionSerializerRegistry`
`spSessionSerializerRegistry`
Mappings between a SPSession type and a serializer implementation.
`private StorageService`
`storageService`
The back-end for managing data.
`private long`
`storageServiceThreshold`
Size boundary below which "large" data can't be stored.
`private boolean`
`trackSPSessions`
Indicates whether to store and track SPSessions.

## Constructor Summary

Constructors
Constructor
Description
`StorageBackedSessionManager()`
Constructor.

## Method Summary

Modifier and Type
Method
Description
`IdPSession`
`createSession(String principalName)`
Create and return a new `IdPSession` object for a subject.
`void`
`destroySession(String sessionId, boolean unbind)`
Invalidates or otherwise removes a session from persistent storage and/or unbinds it from a client.
`protected void`
`doInitialize()`
`AuthenticationFlowDescriptor`
`getAuthenticationFlowDescriptor(String flowId)`
Get a matching `AuthenticationFlowDescriptor`.
`BiPredicate<String,String>`
`getConsistentAddressCondition()`
Get condition to evaluate bound session and client addresses for consistency.
`private HttpServletRequest`
`getHttpRequest()`
Get the `HttpServletRequest` associated with this operation.
`Duration`
`getSessionSlop()`
Get the amount of time to defer expiration of records.
`Duration`
`getSessionTimeout()`
Get the session inactivity timeout policy.
`SPSessionSerializerRegistry`
`getSPSessionSerializerRegistry()`
Get the attached `SPSessionSerializerRegistry`.
`StorageSerializer<StorageBackedIdPSession>`
`getStorageSerializer()`
Get the serializer for the `IdPSession` objects managed by this implementation.
`StorageService`
`getStorageService()`
Get the `StorageService` back-end to use.
`protected void`
`indexBySPSession(IdPSession idpSession, SPSession spSession, int attempts)`
Insert or update a secondary index record from an SPSession to a parent IdPSession.
`boolean`
`isMaskStorageFailure()`
Get whether to mask StorageService failures where possible.
`boolean`
`isSecondaryServiceIndex()`
Get whether to create a secondary index for SPSession lookup.
`boolean`
`isTrackSPSessions()`
Get whether to track SPSessions.
`private IdPSession`
`lookupBySessionId(String sessionId)`
Performs a lookup and deserializes a record based on session ID.
`private Iterable<IdPSession>`
`lookupBySPSession(SPSessionCriterion criterion)`
Performs a lookup and deserializes records potentially matching a SPSession.
`Iterable<IdPSession>`
`resolve(CriteriaSet criteria)`
`IdPSession`
`resolveSingle(CriteriaSet criteria)`
`void`
`setAuthenticationFlowDescriptors(Iterable<AuthenticationFlowDescriptor> flows)`
Set the `AuthenticationFlowDescriptor` collection active in the system.
`void`
`setConsistentAddress(boolean flag)`
Set whether sessions are bound to client addresses either via disabling the comparison or testing simple equality.
`void`
`setConsistentAddressCondition(BiPredicate<String,String> condition)`
Set condition to evaluate bound session and client addresses for consistency.
`void`
`setCookieManager(CookieManager manager)`
Set the `CookieManager` to use.
`void`
`setCookieName(String name)`
Set the cookie name to use for session tracking.
`void`
`setHttpServletRequestSupplier(NonnullSupplier<HttpServletRequest> requestSupplier)`
Set the `NonnullSupplier` for the servlet request to read from.
`void`
`setIDGenerator(IdentifierGenerationStrategy newIDGenerator)`
Set the generator to use when creating XML ID attribute values.
`void`
`setMaskStorageFailure(boolean flag)`
Set whether to mask StorageService failures where possible.
`void`
`setSecondaryServiceIndex(boolean flag)`
Set whether to create a secondary index for SPSession lookup.
`void`
`setSessionSlop(Duration slop)`
Set the amount of time to defer expiration of records.
`void`
`setSessionTimeout(Duration timeout)`
Set the session inactivity timeout policy.
`void`
`setSPSessionSerializerRegistry(SPSessionSerializerRegistry registry)`
Set the `SPSessionSerializerRegistry` to use.
`void`
`setStorageService(StorageService storage)`
Set the `StorageService` back-end to use.
`void`
`setStorageServiceThreshold(long size)`
Set the size in characters that the configured `StorageService` must support in order for "larger" data to be stored, specifically the data involved with the `trackSPSessions` and `secondaryServiceIndex` options.
`void`
`setTrackSPSessions(boolean flag)`
Set whether to track SPSessions.
`boolean`
`storageServiceMeetsThreshold()`
Get whether the configured `StorageService`'s `StorageCapabilities.getValueSize()` method meets the value set via `setStorageServiceThreshold(long)`.
`protected void`
`unindexSPSession(IdPSession idpSession, SPSession spSession, int attempts)`
Remove or update a secondary index record from an SPSession to a parent IdPSession.

### Methods inherited from class net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent

`setId`

### Methods inherited from class net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent

`ensureId, getId, ifDestroyedThrowDestroyedComponentException, ifInitializedThrowUnmodifiabledComponentException, ifNotInitializedThrowUninitializedComponentException`

### Methods inherited from class net.shibboleth.shared.component.AbstractInitializableComponent

`checkComponentActive, checkSetterPreconditions, destroy, doDestroy, initialize, isDestroyed, isInitialized`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Methods inherited from interface net.shibboleth.shared.component.IdentifiedComponent

`getId`

## Field Details

### SESSION_PRIMARY_KEY

@Nonnull @NotEmpty public static final String SESSION_PRIMARY_KEY
Storage key of primary session records.

See Also:
  - Constant Field Values

### DEFAULT_COOKIE_NAME

@Nonnull @NotEmpty protected static final String DEFAULT_COOKIE_NAME
Default cookie name for session tracking.

See Also:
  - Constant Field Values

### log

@Nonnull private final org.slf4j.Logger log
Class logger.

### httpRequestSupplier

@NonnullAfterInit private NonnullSupplier<HttpServletRequest> httpRequestSupplier
Servlet request to read from.

### sessionTimeout

@Nonnull private Duration sessionTimeout
Inactivity timeout for sessions.

### sessionSlop

@Nonnull private Duration sessionSlop
Amount of time to defer expiration of records for better handling of logout.

### maskStorageFailure

private boolean maskStorageFailure
Indicates that storage service failures should be masked as much as possible.

### trackSPSessions

private boolean trackSPSessions
Indicates whether to store and track SPSessions.

### secondaryServiceIndex

private boolean secondaryServiceIndex
Indicates whether to secondary-index SPSessions.

### consistentAddressCondition

@Nonnull private BiPredicate<String,String> consistentAddressCondition
Indicates how bound session addresses and client addresses are compared.

### cookieManager

@NonnullAfterInit private CookieManager cookieManager
Manages creation of cookies.

### cookieName

@Nonnull @NotEmpty private String cookieName
Name of cookie used to track sessions.

### storageService

@NonnullAfterInit private StorageService storageService
The back-end for managing data.

### storageServiceThreshold

private long storageServiceThreshold
Size boundary below which "large" data can't be stored.

### idGenerator

@NonnullAfterInit private IdentifierGenerationStrategy idGenerator
Generator for XML ID attribute values.

### serializer

@Nonnull private final StorageBackedIdPSessionSerializer serializer
Serializer for sessions.

### flowDescriptorMap

@Nonnull private final Map<String,AuthenticationFlowDescriptor> flowDescriptorMap
Flows that could potentially be used to authenticate the user.

### spSessionSerializerRegistry

@Nullable private SPSessionSerializerRegistry spSessionSerializerRegistry
Mappings between a SPSession type and a serializer implementation.

## Constructor Details

### StorageBackedSessionManager

public StorageBackedSessionManager()
Constructor.

## Method Details

### setHttpServletRequestSupplier

public void setHttpServletRequestSupplier(@Nullable NonnullSupplier<HttpServletRequest> requestSupplier)
Set the `NonnullSupplier` for the servlet request to read from.

Parameters:
  `requestSupplier` - servlet request Supplier

### getSessionTimeout

@Nonnull public Duration getSessionTimeout()
Get the session inactivity timeout policy.

Returns:
  inactivity timeout

### setSessionTimeout

public void setSessionTimeout(@Nonnull Duration timeout)
Set the session inactivity timeout policy.

Parameters:
  `timeout` - the policy to set

### getSessionSlop

@Nonnull public Duration getSessionSlop()
Get the amount of time to defer expiration of records.

Returns:
  expiration amount of time to defer expiration of records

### setSessionSlop

public void setSessionSlop(@Nonnull Duration slop)
Set the amount of time to defer expiration of records.

Parameters:
  `slop` - amount of time to defer expiration of records

### isMaskStorageFailure

public boolean isMaskStorageFailure()
Get whether to mask StorageService failures where possible.

Returns:
  true iff StorageService failures should be masked

### setMaskStorageFailure

public void setMaskStorageFailure(boolean flag)
Set whether to mask StorageService failures where possible.

Parameters:
  `flag` - flag to set

### isTrackSPSessions

public boolean isTrackSPSessions()
Get whether to track SPSessions.

Returns:
  true iff SPSessions should be persisted

### setTrackSPSessions

public void setTrackSPSessions(boolean flag)
Set whether to track SPSessions.

This feature requires a StorageService that is not client-side because of space limitations.

Parameters:
  `flag` - flag to set

### isSecondaryServiceIndex

public boolean isSecondaryServiceIndex()
Get whether to create a secondary index for SPSession lookup.

Returns:
  true iff a secondary index for SPSession lookup should be maintained

### setSecondaryServiceIndex

public void setSecondaryServiceIndex(boolean flag)
Set whether to create a secondary index for SPSession lookup.

This feature requires a StorageService that is not client-side.

Parameters:
  `flag` - flag to set

### getConsistentAddressCondition

@Nonnull public BiPredicate<String,String> getConsistentAddressCondition()
Get condition to evaluate bound session and client addresses for consistency.

Returns:
  condition
Since:
  4.0.0

### setConsistentAddress

public void setConsistentAddress(boolean flag)
Set whether sessions are bound to client addresses either via disabling the comparison or testing simple equality.

Parameters:
  `flag` - flag to set

### setConsistentAddressCondition

public void setConsistentAddressCondition(@Nonnull BiPredicate<String,String> condition)
Set condition to evaluate bound session and client addresses for consistency.

Parameters:
  `condition` - condition to set
Since:
  4.0.0

### setCookieName

public void setCookieName(@Nonnull @NotEmpty String name)
Set the cookie name to use for session tracking.

Parameters:
  `name` - cookie name to use

### setCookieManager

public void setCookieManager(@Nonnull CookieManager manager)
Set the `CookieManager` to use.

Parameters:
  `manager` - the CookieManager to use.

### getStorageService

@Nonnull public StorageService getStorageService()
Get the `StorageService` back-end to use.

Returns:
  the back-end to use

### setStorageService

public void setStorageService(@Nonnull StorageService storage)
Set the `StorageService` back-end to use.

Parameters:
  `storage` - the back-end to use

### storageServiceMeetsThreshold

public boolean storageServiceMeetsThreshold()
Get whether the configured `StorageService`'s `StorageCapabilities.getValueSize()` method meets the value set via `setStorageServiceThreshold(long)`.

Returns:
  true iff the threshold is met

### setStorageServiceThreshold

public void setStorageServiceThreshold(long size)
Set the size in characters that the configured `StorageService` must support in order for "larger" data to be stored, specifically the data involved with the `trackSPSessions` and `secondaryServiceIndex` options.

The implementation will query the configured service each time it needs to honor those options, to handle cases where the size limit can vary by request.

Defaults to 1024 * 1024 characters.

Parameters:
  `size` - size in characters

### setIDGenerator

public void setIDGenerator(@Nonnull IdentifierGenerationStrategy newIDGenerator)
Set the generator to use when creating XML ID attribute values.

Parameters:
  `newIDGenerator` - the new IdentifierGenerator to use

### getStorageSerializer

@Nonnull public StorageSerializer<StorageBackedIdPSession> getStorageSerializer()
Get the serializer for the `IdPSession` objects managed by this implementation.

Returns:
  the serializer to use when writing back session objects

### getAuthenticationFlowDescriptor

@Nullable public AuthenticationFlowDescriptor getAuthenticationFlowDescriptor(@Nonnull @NotEmpty String flowId)
Get a matching `AuthenticationFlowDescriptor`.

Parameters:
  `flowId` - the ID of the flow to return
Returns:
  the matching flow descriptor, or null

### getHttpRequest

@Nullable private HttpServletRequest getHttpRequest()
Get the `HttpServletRequest` associated with this operation.

Returns:
  the `HttpServletRequest`

### setAuthenticationFlowDescriptors

public void setAuthenticationFlowDescriptors(@Nonnull Iterable<AuthenticationFlowDescriptor> flows)
Set the `AuthenticationFlowDescriptor` collection active in the system.

Parameters:
  `flows` - the flows available for possible use

### getSPSessionSerializerRegistry

@Nullable public SPSessionSerializerRegistry getSPSessionSerializerRegistry()
Get the attached `SPSessionSerializerRegistry`.

Returns:
  a registry of SPSession class to serializer mappings

### setSPSessionSerializerRegistry

public void setSPSessionSerializerRegistry(@Nullable SPSessionSerializerRegistry registry)
Set the `SPSessionSerializerRegistry` to use.

Parameters:
  `registry` - a registry of SPSession class to serializer mappings

### doInitialize

protected void doInitialize() throws ComponentInitializationException

Overrides:
  `doInitialize` in class `AbstractIdentifiedInitializableComponent`
Throws:
  `ComponentInitializationException`

### createSession

@Nonnull public IdPSession createSession(@Nonnull @NotEmpty String principalName) throws SessionException
Create and return a new `IdPSession` object for a subject.

Implementations may perform additional work to persist or associate the session with the client.

Specified by:
  `createSession` in interface `SessionManager`
Parameters:
  `principalName` - canonical name of the subject of the session
Returns:
  the newly created session
Throws:
  `SessionException` - if the session cannot be created

### destroySession

public void destroySession(@Nonnull @NotEmpty String sessionId, boolean unbind) throws SessionException
Invalidates or otherwise removes a session from persistent storage and/or unbinds it from a client.

After calling this method, no further method calls on a corresponding `IdPSession` object that may be in hand are guaranteed to function correctly. Their behavior is unspecified.

Specified by:
  `destroySession` in interface `SessionManager`
Parameters:
  `sessionId` - the unique ID of the session to destroy
  `unbind` - whether the session should be unbound from the client
Throws:
  `SessionException` - if the session cannot be destroyed

### resolve

@Nonnull @Unmodifiable @NotLive public Iterable<IdPSession> resolve(@Nullable CriteriaSet criteria) throws ResolverException

Specified by:
  `resolve` in interface `Resolver<IdPSession,CriteriaSet>`
Throws:
  `ResolverException`

### resolveSingle

@Nullable public IdPSession resolveSingle(@Nullable CriteriaSet criteria) throws ResolverException

Specified by:
  `resolveSingle` in interface `Resolver<IdPSession,CriteriaSet>`
Throws:
  `ResolverException`

### indexBySPSession

protected void indexBySPSession(@Nonnull IdPSession idpSession, @Nonnull SPSession spSession, int attempts) throws SessionException
Insert or update a secondary index record from an SPSession to a parent IdPSession.

Parameters:
  `idpSession` - the parent session
  `spSession` - the SPSession to index
  `attempts` - number of times to retry operation in the event of a synchronization issue
Throws:
  `SessionException` - if a fatal error occurs

### unindexSPSession

protected void unindexSPSession(@Nonnull IdPSession idpSession, @Nonnull SPSession spSession, int attempts) throws SessionException
Remove or update a secondary index record from an SPSession to a parent IdPSession.

Parameters:
  `idpSession` - the parent session
  `spSession` - the SPSession to de-index
  `attempts` - number of times to retry operation in the event of a synchronization issue
Throws:
  `SessionException` - if a fatal error occurs

### lookupBySessionId

@Nullable private IdPSession lookupBySessionId(@Nullable String sessionId) throws ResolverException
Performs a lookup and deserializes a record based on session ID.

Parameters:
  `sessionId` - the session to lookup
Returns:
  the IdPSession object, or null
Throws:
  `ResolverException` - if an error occurs during lookup

### lookupBySPSession

@Nonnull private Iterable<IdPSession> lookupBySPSession(@Nonnull SPSessionCriterion criterion) throws ResolverException
Performs a lookup and deserializes records potentially matching a SPSession.

Parameters:
  `criterion` - the SPSessionCriterion to apply
Returns:
  collection of zero or more sessions
Throws:
  `ResolverException` - if an error occurs during lookup