如何在没有会话的情况下使用Spring Security?

Jar*_*son 94 spring load-balancing spring-security amazon-ec2

我正在使用Spring Security构建一个Web应用程序,该应用程序将存在于Amazon EC2上并使用Amazon的Elastic Load Balancers.不幸的是,ELB不支持粘性会话,因此我需要确保我的应用程序在没有会话的情况下正常工作.

到目前为止,我已经设置了RememberMeServices来通过cookie分配令牌,这很好用,但我希望cookie随浏览器会话一起过期(例如当浏览器关闭时).

我不得不想象我不是第一个想要在没有会话的情况下使用Spring Security的人......有什么建议吗?

Ben*_*son 114

在带有Java Config的 Spring Security 3中,您可以使用HttpSecurity.sessionManagement():

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Run Code Online (Sandbox Code Playgroud)

  • 这是Java配置的正确答案,反映了@sappenin在对接受的答案的评论中为xml配置正确声明的内容.我们使用这种方法,确实我们的应用程序是无会话的. (2认同)

Jar*_*son 28

在Spring Securitiy 3.0中,它似乎更容易.如果您正在使用命名空间配置,则可以执行以下操作:

<http create-session="never">
  <!-- config -->
</http>
Run Code Online (Sandbox Code Playgroud)

或者你可以配置SecurityContextRepository为空,并没有什么会永远得救这样.

  • 这不起作用,因为我认为它会.相反,下面有一个评论区分"从不"和"无国籍".使用"never",我的应用程序仍在创建会话.使用"无状态",我的应用程序实际上是无状态的,我不需要实现其他答案中提到的任何覆盖.请在此处查看JIRA问题:https://jira.springsource.org/browse/SEC-1424 (5认同)

Bas*_*eci 26

我们今天处理了相同的问题(向SecurityContextPersistenceFilter注入自定义SecurityContextRepository)4-5小时.最后,我们弄明白了.首先,在Spring Security引用的8.3节中.doc,有一个SecurityContextPersistenceFilter bean定义

<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name='securityContextRepository'>
        <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
            <property name='allowSessionCreation' value='false' />
        </bean>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

在此定义之后,有这样的解释:"或者,您可以提供SecurityContextRepository接口的null实现,这将阻止安全上下文的存储,即使在请求期间已经创建了会话."

我们需要将自定义SecurityContextRepository注入SecurityContextPersistenceFilter.因此,我们只需使用自定义impl更改上面的bean定义,并将其置于安全上下文中.

当我们运行应用程序时,我们跟踪日志并看到SecurityContextPersistenceFilter没有使用我们的自定义impl,它使用的是HttpSessionSecurityContextRepository.

在我们尝试了一些其他的事情之后,我们发现我们必须使用"http"命名空间的"security-context-repository-ref"属性给我们的自定义SecurityContextRepository impl.如果您使用"http"命名空间并想要注入自己的SecurityContextRepository impl,请尝试"security-context-repository-ref"属性.

使用"http"命名空间时,将忽略单独的SecurityContextPersistenceFilter定义.正如我上面复制的那样,参考文档.没有说明.

如果我误解了这些事情,请纠正我.


小智 10

看看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>
Run Code Online (Sandbox Code Playgroud)


hle*_*one 8

实际上create-session="never"并不意味着完全无国籍.Spring Security问题管理中存在一个问题.