Управление сессиями в Spring Security
Я новичок в Spring Security. У меня есть требование сделать аутентификацию на основе URL-адреса, при которой пользователь должен пройти аутентификацию на основе уникальной ссылки, которая будет отправляться каждый раз в качестве параметра в URL-адресе. Я передам эту ссылку веб-службе, получу необходимые данные, а затем аутентифицирую пользователя (и установлю роли). Часть Аутентификация и авторизация работает нормально.
Тем не менее, когда я пытаюсь снова получить доступ к приложению (теперь с другой ссылкой в URL), он говорит "SecurityContextHolder не заполнен анонимным токеном, так как он уже содержал...", и он показывает детали предыдущего запроса. Я попытался очистить контекст безопасности с помощью SecurityContextHolder.getContext(). SetAuthentication(null) и SecurityContextHolder.clearContext().
После этого я смог получить доступ к приложению несколько раз. Однако, если я пытаюсь получить доступ к приложению одновременно с компьютера моего коллеги, я получаю пустую страницу. После проверки журналов я вижу сообщение "SecurityContextHolder не заполнен анонимным токеном...". Я также пытался настроить сессии, но я не знаю, где проигрываю трек.
Ниже мой web.xml (только часть безопасности весны):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
весна-security.xml:
<http use-expressions="true" auto-config="false" entry-point-
ref="http403ForbiddenEntryPoint">
<intercept-url pattern="/paymentPortalInternal.*" access="hasRole('Internal')"/>
<intercept-url pattern="/paymentPortalExternal.*" access="hasRole('External')"/>
<custom-filter position="PRE_AUTH_FILTER" ref="customAuthenticationFilter"/>
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<session-management session-authentication-strategy-ref="sas"/>
</http>
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/session-expired.htm" />
</beans:bean>
<beans:bean id="http403ForbiddenEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<beans:bean id="customAuthenticationFilter"
class="com.xxx.xxx.xxxxx.security.CustomAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.
ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<beans:bean id="preauthAuthProvider"
class="org.springframework.security.web.authentication.preauth.
PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean class="com.XXX.XXXX.XXX.UserServiceImpl" />
</beans:property>
</beans:bean>
Пожалуйста, дайте мне знать, если мне нужно предоставить больше информации.
РЕДАКТИРОВАТЬ: Добавление журналов.
Для первого запроса:
2013-02-07 17: 27: 38,834 DEBUG [http-8081-2] [org.springframework.security.web.context.HttpSessionSecurityContextRepository.readSecurityContextFromSession (127)] - в настоящее время HttpSession не существует 2013-02-07 17:27:38,834 DEBUG [http-8081-2][org.springframework.security.web.context.HttpSessionSecurityContextRepository.loadContext(85)]. От HttpSession: null не было никакого защищенного контекста. Новый будет создан.
Для второго запроса (обратите внимание, что детали в контексте безопасности те же, что и в первом запросе):
2013-02-07 17: 27: 54,272 DEBUG [http-8081-2] [org.springframework.security.web.context.HttpSessionSecurityContextRepository.readSecurityContextFromSession (158)] - получен действительный аргумент SecurityContext из SPRING_SECURITY_CONText:, -41bb-9257-b3c1acb96519; Пароль защищен]; Включено: правда; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Предоставленные полномочия: внутренние; Полномочия: [ЗАЩИЩЕНО]; Аутентифицировано: правда; Подробности: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffc434: RemoteIpAddress: 10.188.182.107; SessionId: null; Предоставленные полномочия: внутренние "
Насколько я понимаю, владелец контекста безопасности хранит информацию обо всех пользователях. Но в этом случае я не могу запустить приложение из другой вкладки / браузера.
2 ответа
Мне удалось исправить эту проблему, переопределив цепочку фильтров по умолчанию (используется прокси цепочки фильтров) и вызвав только необходимые фильтры. Спасибо LukeTaylor и Ketan за ваши предложения. Пожалуйста, дайте мне знать, если у кого-то есть такая же проблема. Я могу опубликовать свой XML и другие вещи.
Если ваш CustomAuthenticationFilter расширяется AbstractPreAuthenticatedProcessingFilter
, следующие 2 свойства могут дать вам понимание. 1. checkForPrincipalChanges
2. invalidateSessionOnPrincipalChange