Sunday, September 23, 2007

Session Limitation with Spring security

Sometimes it's useful to restrict a user a single session. This simplifies the logic needed to guarantee certain restrictions. For example, I always want a user to have a minimum of one valid email address. With two parallel sessions and two valid emails a user could delete one email in each session and I would need to verify consistency in the database. Restrictig to one session lets me implement the restriction in the business logic. However, the exact configuration was not obvious. After some experimentation the following seemed to work. First, you need some way of detectig when sessions expire. This is largely automatic as long as you register the following in web.xml:

  <!-- used to track session events (single user session) -->
  <listener>
    <listener-class>org.acegisecurity.ui.\
      session.HttpSessionEventPublisher</listener-class>
  </listener>
I have all my authentication-related xml in web-authentication.xml (and referenced via context-param in web.xml). It includes:
  <bean id="authenticationManager"
    class="org.acegisecurity.providers.ProviderManager">
    <property name="sessionController" ref="singleSession"/>
    <property name="providers">
      ...
    </property>
  </bean>

  <bean id="sessionRegistry"
    class="org.acegisecurity.concurrent.SessionRegistryImpl"/>

  <bean id="singleSession"
    class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
    <property name="maximumSessions" value="1"/>
    <property name="exceptionIfMaximumExceeded" value="true"/>
    <property name="sessionRegistry" ref="sessionRegistry"/>
  </bean>
Which is all that is needed (I suspect sessionRegistry is supplied by default anyway). The way it seems to work is as follows: - authenticationManager calls the appropriate provider - if that succeeds, it calls sessionController - sessionController applies the appropriate logic, using the information in sessionRegistry - sessionRegistry is correct because of the event system (which includes the listener you registered).
By Andrew

No comments: