session-mgmt.xml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="session-mgmt"
  2. xmlns:xlink="http://www.w3.org/1999/xlink">
  3. <info>
  4. <title>Session Management</title>
  5. </info>
  6. <para>HTTP session related functonality is handled by a combination of the
  7. <classname>SessionManagementFilter</classname> and the
  8. <interfacename>SessionAuthenticationStrategy</interfacename> interface, which the filter
  9. delegates to. Typical usage includes session-fixation protection attack prevention,
  10. detection of session timeouts and restrictions on how many sessions an authenticated user
  11. may have open concurrently.</para>
  12. <section>
  13. <title>SessionManagementFilter</title>
  14. <para>The <classname>SessionManagementFilter</classname> checks the contents of the
  15. <interfacename>SecurityContextRepository</interfacename> against the current contents of
  16. the <classname>SecurityContextHolder</classname> to determine whether a user has been
  17. authenticated during the current request, typically by a non-interactive authentication
  18. mechanism, such as pre-authentication or remember-me <footnote>
  19. <para>Authentication by mechanisms which perform a redirect after authenticating (such
  20. as form-login) will not be detected by
  21. <classname>SessionManagementFilter</classname>, as the filter will not be invoked
  22. during the authenticating request. Session-management functionality has to be
  23. handled separately in these cases. </para>
  24. </footnote>. If the repository contains a security context, the filter does nothing. If
  25. it doesn't, and the thread-local <interfacename>SecurityContext</interfacename> contains
  26. a (non-anonymous) <interfacename>Authentication</interfacename> object, the filter
  27. assumes they have been authenticated by a previous filter in the stack. It will then
  28. invoke the configured
  29. <interfacename>SessionAuthenticationStrategy</interfacename>.</para>
  30. <para>If the user is not currently authenticated, the filter will check whether an invalid
  31. session ID has been requested (because of a timeout, for example) and will invoke the configured
  32. <interfacename>InvalidSessionStrategy</interfacename>, if one is set. The most common behaviour
  33. is just to redirect to a fixed URL and this is encapsulated in the standard implementation
  34. <classname>SimpleRedirectInvalidSessionStrategy</classname>. The latter is also used
  35. when configuring an invalid session URL through the namespace,
  36. <link xlink:href="#ns-session-mgmt">as described earlier</link>.</para>
  37. </section>
  38. <section>
  39. <title><interfacename>SessionAuthenticationStrategy</interfacename></title>
  40. <para> <interfacename>SessionAuthenticationStrategy</interfacename> is used by both
  41. <classname>SessionManagementFilter</classname> and
  42. <classname>AbstractAuthenticationProcessingFilter</classname>, so if you are using a
  43. customized form-login class, for example, you will need to inject it into both of these.
  44. In this case, a typical configuration, combining the namespace and custom beans might
  45. look like this:<programlisting language="xml"><![CDATA[
  46. <http>
  47. <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
  48. <session-management session-authentication-strategy-ref="sas"/>
  49. </http>
  50. <beans:bean id="myAuthFilter" class=
  51. "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
  52. <beans:property name="sessionAuthenticationStrategy" ref="sas" />
  53. ...
  54. </beans:bean>
  55. <beans:bean id="sas" class=
  56. "org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
  57. ]]></programlisting>
  58. Note that the use of the default, <classname>SessionFixationProtectionStrategy</classname>
  59. may cause issues if you are storing beans in the session which implement
  60. <interfacename>HttpSessionBindingListener</interfacename>, including Spring session-scoped
  61. beans. See the Javadoc for this class for more information.
  62. </para>
  63. </section>
  64. <section xml:id="concurrent-sessions">
  65. <title>Concurrency Control</title>
  66. <para>Spring Security is able to prevent a principal from concurrently authenticating to the
  67. same application more than a specified number of times. Many ISVs take advantage of this
  68. to enforce licensing, whilst network administrators like this feature because it helps
  69. prevent people from sharing login names. You can, for example, stop user
  70. <quote>Batman</quote> from logging onto the web application from two different sessions.
  71. You can either expire their previous login or you can report an error when they try to
  72. log in again, preventing the second login. Note that if you are using the second
  73. approach, a user who has not explicitly logged out (but who has just closed their
  74. browser, for example) will not be able to log in again until their original session
  75. expires.</para>
  76. <para>Concurrency control is supported by the namespace, so please check the earlier
  77. namespace chapter for the simplest configuration. Sometimes you need to customize things
  78. though. </para>
  79. <para>The implementation uses a specialized version of
  80. <interfacename>SessionAuthenticationStrategy</interfacename>, called
  81. <classname>ConcurrentSessionControlAuthenticationStrategy</classname>. <note>
  82. <para>Previously the concurrent authentication check was made by the
  83. <classname>ProviderManager</classname>, which could be injected with a
  84. <literal>ConcurrentSessionController</literal>. The latter would check if the user
  85. was attempting to exceed the number of permitted sessions. However, this approach
  86. required that an HTTP session be created in advance, which is undesirable. In Spring
  87. Security 3, the user is first authenticated by the
  88. <interfacename>AuthenticationManager</interfacename> and once they are successfully
  89. authenticated, a session is created and the check is made whether they are allowed
  90. to have another session open.</para>
  91. </note></para>
  92. <para>To use concurrent session support, you'll need to add the following to
  93. <literal>web.xml</literal>: <programlisting language="xml"><![CDATA[
  94. <listener>
  95. <listener-class>
  96. org.springframework.security.web.session.HttpSessionEventPublisher
  97. </listener-class>
  98. </listener> ]]>
  99. </programlisting></para>
  100. <para>In addition, you will need to add the <literal>ConcurrentSessionFilter</literal> to
  101. your <classname>FilterChainProxy</classname>. The
  102. <classname>ConcurrentSessionFilter</classname> requires two properties,
  103. <literal>sessionRegistry</literal>, which generally points to an instance of
  104. <classname>SessionRegistryImpl</classname>, and <literal>expiredUrl</literal>, which
  105. points to the page to display when a session has expired. A configuration using the
  106. namespace to create the <classname>FilterChainProxy</classname> and other default beans
  107. might look like this: <programlisting language="xml"><![CDATA[
  108. <http>
  109. <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
  110. <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
  111. <session-management session-authentication-strategy-ref="sas"/>
  112. </http>
  113. <beans:bean id="concurrencyFilter"
  114. class="org.springframework.security.web.session.ConcurrentSessionFilter">
  115. <beans:property name="sessionRegistry" ref="sessionRegistry" />
  116. <beans:property name="expiredUrl" value="/session-expired.htm" />
  117. </beans:bean>
  118. <beans:bean id="myAuthFilter" class=
  119. "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
  120. <beans:property name="sessionAuthenticationStrategy" ref="sas" />
  121. <beans:property name="authenticationManager" ref="authenticationManager" />
  122. </beans:bean>
  123. <beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
  124. <beans:constructor-arg>
  125. <beans:list>
  126. <beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
  127. <beans:constructor-arg ref="sessionRegistry"/>
  128. <beans:property name="maximumSessions" value="1" />
  129. <beans:property name="exceptionIfMaximumExceeded" value="true" />
  130. </beans:bean>
  131. <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
  132. </beans:bean>
  133. <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
  134. <beans:constructor-arg ref="sessionRegistry"/>
  135. </beans:bean>
  136. </beans:list>
  137. </beans:constructor-arg>
  138. </beans:bean>
  139. <beans:bean id="sessionRegistry"
  140. class="org.springframework.security.core.session.SessionRegistryImpl" />
  141. ]]>
  142. </programlisting></para>
  143. <para>Adding the listener to <filename>web.xml</filename> causes an
  144. <literal>ApplicationEvent</literal> to be published to the Spring
  145. <literal>ApplicationContext</literal> every time a <literal>HttpSession</literal>
  146. commences or terminates. This is critical, as it allows the
  147. <classname>SessionRegistryImpl</classname> to be notified when a session ends. Without
  148. it, a user will never be able to log back in again once they have exceeded their session
  149. allowance, even if they log out of another session or it times out.</para>
  150. <section xml:id="list-authenticated-principals">
  151. <title>Querying the <interfacename>SessionRegistry</interfacename> for currently authenticated
  152. users and their sessions</title>
  153. <para>
  154. Setting up concurrency-control, either through the namespace or using plain beans has the
  155. useful side effect of providing you with a reference to the <interfacename>SessionRegistry</interfacename>
  156. which you can use directly within your application, so even if you don't want to restrict the
  157. number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can
  158. set the <literal>maximumSession</literal> property to -1 to allow unlimited sessions. If
  159. you're using the namespace, you can set an alias for the internally-created
  160. <interfacename>SessionRegistry</interfacename> using the <literal>session-registry-alias</literal>
  161. attribute, providing a reference which you can inject into your own beans.</para>
  162. <para>
  163. The <methodname>getAllPrincipals()</methodname>
  164. method supplies you with a list of the currently authenticated users. You can list a user's
  165. sessions by calling the <methodname>getAllSessions(Object principal, boolean includeExpiredSessions)</methodname> method,
  166. which returns a list of <classname>SessionInformation</classname> objects. You can also
  167. expire a user's session by calling <methodname>expireNow()</methodname> on a
  168. <methodname>SessionInformation</methodname> instance. When the user returns to the application, they
  169. will be prevented from proceeding. You may find these methods useful in an administration
  170. application, for example. Have a look at the Javadoc for more information.
  171. </para>
  172. </section>
  173. </section>
  174. </chapter>