Я создаю веб-приложение с безопасностью Spring, которая будет жить на Amazon EC2 и использовать Эластичные Подсистемы балансировки нагрузки Amazon. К сожалению, ELB не поддерживает липкие сессии, таким образом, я должен удостовериться, что мое приложение работает правильно без сессий.
До сих пор я имею, устанавливают RememberMeServices для присвоения маркера через cookie, и это хорошо работает, но я хочу, чтобы cookie истек с сеансом браузера (например, когда браузер закрывается).
Я должен предположить, что я не первый, который захочет использовать безопасность Spring без сессий... какие-либо предложения?
В Spring Securitiy 3.0 это стало еще проще. Если вы используете конфигурацию пространства имен, вы можете просто сделать следующее:
<http create-session="never">
<!-- config -->
</http>
Или вы можете настроить SecurityContextRepository как null, и ничто никогда не будет сохранено таким образом .
Небольшое примечание: это «create-session», а не «create-sessions»
Управляет энергией, с которой создается сеанс HTTP.
Если не установлен, по умолчанию используется «ifRequired». Другие варианты: « always »и« never ».
Установка этого атрибута влияет на свойства allowSessionCreation и forceEagerSessionCreation HttpSessionContextIntegrationFilter. allowSessionCreation всегда будет истинным, если для этого атрибута не установлено значение« never ». forceEagerSessionCreation имеет значение« false », если не установлено значение« always ».
Таким образом, конфигурация по умолчанию разрешает создание сеанса, но не заставляет его. Исключение составляет, если включено управление параллельным сеансом, когда forceEagerSessionCreation будет b e установлено значение true, независимо от того, какой здесь параметр. Использование «никогда» вызовет исключение во время инициализации HttpSessionContextIntegrationFilter.
Конкретные подробности использования сеанса можно найти в документации Javadoc HttpSessionSecurityContextRepository.
Взгляните на класс SecurityContextPersistenceFilter
. Он определяет, как заполняется SecurityContextHolder
. По умолчанию он использует HttpSessionSecurityContextRepository
для хранения контекста безопасности в сеансе http.
Я довольно легко реализовал этот механизм с помощью специального SecurityContextRepository
.
См. securityContext.xml
ниже:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<context:annotation-config/>
<sec:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>
<bean id="securityContextRepository" class="com.project.server.security.TokenSecurityContextRepository"/>
<bean id="securityContextFilter" class="com.project.server.security.TokenSecurityContextPersistenceFilter">
<property name="repository" ref="securityContextRepository"/>
</bean>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/login.jsp"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="formLoginFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler">
<bean class="com.project.server.security.TokenAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/index.html"/>
<property name="passwordExpiredUrl" value="/changePassword.jsp"/>
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>
</property>
<property name="authenticationFailureHandler">
<bean class="com.project.server.modules.security.CustomUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?failure=1"/>
</bean>
</property>
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
<property name="allowSessionCreation" value="false"/>
</bean>
<bean id="servletApiFilter"
class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
<bean id="anonFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="ClientApplication"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="exceptionTranslator" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/login.jsp?failure=2"/>
</bean>
</property>
<property name="requestCache">
<bean id="nullRequestCache" class="org.springframework.security.web.savedrequest.NullRequestCache"/>
</property>
</bean>
<alias name="filterChainProxy" alias="springSecurityFilterChain"/>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/**"
filters="securityContextFilter, logoutFilter, formLoginFilter,
servletApiFilter, anonFilter, exceptionTranslator, filterSecurityInterceptor"/>
</sec:filter-chain-map>
</bean>
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="securityMetadataSource">
<sec:filter-security-metadata-source use-expressions="true">
<sec:intercept-url pattern="/staticresources/**" access="permitAll"/>
<sec:intercept-url pattern="/index.html*" access="hasRole('USER_ROLE')"/>
<sec:intercept-url pattern="/rpc/*" access="hasRole('USER_ROLE')"/>
<sec:intercept-url pattern="/**" access="permitAll"/>
</sec:filter-security-metadata-source>
</property>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
<bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
</list>
</property>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<bean name="authenticationProvider"
class="com.project.server.modules.security.oracle.StoredProcedureBasedAuthenticationProviderImpl">
<property name="dataSource" ref="serverDataSource"/>
<property name="userDetailsService" ref="userDetailsService"/>
<property name="auditLogin" value="true"/>
<property name="postAuthenticationChecks" ref="customPostAuthenticationChecks"/>
</bean>
</list>
</property>
</bean>
<bean id="customPostAuthenticationChecks" class="com.project.server.modules.security.CustomPostAuthenticationChecks"/>
<bean name="userDetailsService" class="com.project.server.modules.security.oracle.UserDetailsServiceImpl">
<property name="dataSource" ref="serverDataSource"/>
</bean>
</beans>
На самом деле create-session="never"
не означает быть полностью stateless. Для этого есть проблема в управлении проблемами Spring Security.