barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

вторник, 9 октября 2012 г.

Spring Security 3.1: получение списка залогиненных пользователей

Задача:

Получить список залогиненных пользователей (например, чтобы разлогинить некоторых из них).

Решение:

Для решения этой задачи можно воспользоваться реестром пользовательских сессий, который используется Spring Security, в частности, для контроля множественного входа под одним логином. Чтобы реестр заполнялся и к нему можно было получить доступ из собственного кода, нужно (если, конечно, у Вас уже не используется контроль множественного входа):
  1. В web.xml добавить слушателя:
    <listener>
      <listener-class>
    org.springframework.security.web.session.HttpSessionEventPublisher
      </listener-class>
    </listener>
  2. В конфигурацию Spring Security добавить:


    <!-- Задаем точку входа и страницу запрета доступа, обязательно
      -- отключаем auto-config, чтобы определить свой фильтр для входа
      -- по логину/паролю
      -->
    <http auto-config="false" access-denied-page="/login.jsp?accessDeniedError=1"
              entry-point-ref="authenticationProcessingFilterEntryPoint">

            <custom-filter position="FORM_LOGIN_FILTER" ref="usernamePasswordFilter" />
         
    <!-- Далее идут правила доступа -->
            <intercept-url ... />
    ...  
    <!-- Указываем ссылку на бин для session-managment`а -->
            <session-management session-authentication-strategy-ref="sas"/>
    <!-- Конфигурация выхода обыкновенная -->
            <logout delete-cookies="JSESSIONID" logout-url="/j_spring_security_logout"/>
    </http>

    <!-- Конфигурируем точку входа в приложение -->
    <beans:bean id="authenticationProcessingFilterEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:property name="loginFormUrl" value="/login.jsp" />
    <beans:property name="forceHttps" value="false" />
    </beans:bean>

    <!-- Конфигурируем реестр сессий -->
    <beans:bean id="sessionRegistry"
    class="org.springframework.security.core.session.SessionRegistryImpl" />

    <!-- Конфигурируем бин стратегии контроля сессий. Не ограничиваем
      -- множественность входа (нам это сейчас не нужно, по этой же причине
      -- мы не использовали фильтр ConcurrentSessionFilter)
      -->
    <beans:bean id="sas" class=
    "org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
    <beans:constructor-arg ref="sessionRegistry" />
    <beans:property name="maximumSessions" value="-1" />
    </beans:bean>

    <!-- Конфигурируем фильтр входа по логину / паролю, задавая ссылку на стратегию,
      -- а также ссылки на бины обработчиков успешного / неуспешного входа
      -->
    <beans:bean id="usernamePasswordFilter" class=
                "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <beans:property name="sessionAuthenticationStrategy" ref="sas" />
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationFailureHandler" ref="loginFailureHandler"/>
    <beans:property name="authenticationSuccessHandler" ref="loginSuccessHandler"/>
    </beans:bean>

    <!-- Менеджер аутентификации. Тут все стандартно, задается один какой-то провайдер
      -- и для стандартного провайдера задается какой-то UserService
      -->
    <authentication-manager alias="authenticationManager">
    <authentication-provider ref="..."/>
    <authentication-provider user-service-ref='...'>
    <password-encoder hash="md5" />
    </authentication-provider>
    </authentication-manager>

    <!-- Обработчики успешного / неуспешного логина. Стандартные -->
    <beans:bean id="loginSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler" >
    <beans:property name="defaultTargetUrl" value="/index.jsp"/>
    </beans:bean>

    <beans:bean id="loginFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" >
    <beans:property name="defaultFailureUrl" value="/login.jsp?loginError=1" />
    </beans:bean>

  3. Теперь получить реестр и список активных принципалов в коде можно так:
    import org.springframework.security.core.session.SessionRegistry;
    import org.springframework.web.context.support.WebApplicationContextUtils;

    ...

    ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
    SessionRegistry sReg = (SessionRegistry) ac.getBean("sessionRegistry");
    for(Object principal: sReg.getAllPrincipals())
         System.out.println("Principal: "+principal.toString());

PS Надо, пожалуй, озаботиться подсветкой синтаксиса в блоге =)

Комментариев нет:

Отправить комментарий