Class 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.

  • 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
    • log

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

      @Nullable private javax.servlet.http.HttpServletRequest httpRequest
      Servlet request to read from.
    • httpResponse

      @Nullable private javax.servlet.http.HttpServletResponse httpResponse
      Servlet response to write to.
    • 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

      Generator for XML ID attribute values.
    • serializer

      @Nonnull private final StorageBackedIdPSessionSerializer serializer
      Serializer for sessions.
    • flowDescriptorMap

      @Nonnull @NonnullElements 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

    • setHttpServletRequest

      public void setHttpServletRequest​(@Nullable javax.servlet.http.HttpServletRequest request)
      Set the servlet request to read from.
      Parameters:
      request - servlet request
    • setHttpServletResponse

      public void setHttpServletResponse​(@Nullable javax.servlet.http.HttpServletResponse response)
      Set the servlet response to write to.
      Parameters:
      response - servlet response
    • 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)
      Parameters:
      flowId - the ID of the flow to return
      Returns:
      the matching flow descriptor, or null
    • setAuthenticationFlowDescriptors

      public void setAuthenticationFlowDescriptors​(@Nonnull @NonnullElements 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)
      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 @NonnullElements 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 @NonnullElements 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