7

背景

大家好,我们有Spring使用Spring security. 我们通过定义定义了安全过滤器

 <b:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

哪里filter-chain-map

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>

一切都很好:)。现在Spring session根据 以下几行进行连接redisdoc

<context:annotation-config />
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

创建一个filter名为springSessionRepositoryFilter. 所以基本上我们所做的就是在每个自定义filter-chain中添加该过滤器作为第一个过滤器。IE:

<b:bean id="springSecurityFilterChain"   class="org.springframework.security.web.FilterChainProxy">
     <filter-chain-map request-matcher="ant">

           <filter-chain pattern="/api/someapieformobilelogin" filters="none" />  <!-- no filter on login -->
        <filter-chain pattern="/api/**"
            filters="springSessionRepositoryFilter, securityContextFilter,and some other spring security filter />

        <filter-chain pattern="/**"
            filters="springSessionRepositoryFilter, securityContextFilter,and some other spring security filter />

结果:该应用程序似乎运行良好,并且monitoring通过redis-cli显示spring正在与之通信redis

问题

springSessionRepositoryFilter里面使用filter-chain可以吗?还是我们滥用了过滤系统?

谢谢,

橡木

编辑

似乎上述方法不适用于希望Authenticate从代码中获取用户的情况,即

Authentication authentication = authenticationManager
                .authenticate(authenticationToken);
SecurityContext securityContext = SecurityContextHolder
                .getContext();
securityContext.setAuthentication(authentication);

将失败。也许是因为它不足以通过filter-chainof运行它org.springframework.security.web.FilterChainProxy

你觉得如何运行filterweb.xml

<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

以上将强制运行springSessionRepositoryFilterspringSecurityFilterChain但在此示例org.springframework.web.filter.DelegatingFilterProxy中被调用两次。springSessionRepositoryFilter在过滤器之前作为过滤器运行的任何其他方法springSecurityFilterChain

4

2 回答 2

2

根据我的测试, springSessionRepositoryFilter必须先运行。springSessionRepositoryFilter这是由于替换实现的事实HttpSession。这是我使用xml文件的解决方案。

redis-cache.xml

<context:annotation-config />
<bean
    class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />

<bean
    class="org.springframework.security.web.session.HttpSessionEventPublisher" />

<!-- end of seesion managment configuration -->


<bean id="redisConnectionFactory"
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="port" value="${app.redis.port}" />
    <property name="hostName" value="${app.redis.hostname}" />
    <property name="password" value="${app.redis.password}" />
    <property name="usePool" value="true" />
</bean>

我们使用和 RedisHttpSessionConfiguration 的组合,因为 Spring Session 还没有提供 XML Namespace 支持(参见 gh-104)。这将创建一个名为 springSessionRepositoryFilter 的 Spring Bean,它实现了 Filter。过滤器负责替换 Spring Session 支持的 HttpSession 实现。在这种情况下,Spring Session 由 Redis 支持。 资源

现在,正如我们session filter命名的springSessionRepositoryFilter那样,它必须作为第一个过滤器运行,因为它替换了HttpSession实现。

为此,我们将其声明为web.xml. 有关过滤器和过滤器顺序的更多信息,请查看文档

web.xml

<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>


<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    /WEB-INF/redis-cache.xml
    </param-value>
</context-param>

 <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

请注意,第一个运行的是springSessionRepositoryFilter. 但实际上org.springframework.web.filter.DelegatingFilterProxy类正在运行,它通过 bean 的名称查找过滤器。因此它会搜索我们早期配置创建的 bean。 参考

关于 的额外行redis-cache.xml也很重要。否则我们spring application context无法知道我们的 redis 配置

参考

于 2016-10-30T07:37:47.463 回答
1

不要紧。从Javadoc

SessionRepositoryFilter 必须放在任何访问 HttpSession 或可能提交响应的过滤器之前,以确保会话被覆盖并正确保留。

只要您springSessionRepositoryFilter在可以提交响应或访问的任何内容之前添加,就可以了HttpSession。在 Spring Security 的情况下,您要确保的主要事情springSessionRepositoryFilter是在SecurityContextPersistenceFilter. 这可以通过包含springSessionRepositoryFilter在容器中或 Spring Security FilterChainProxy(即<filter-chain>)中来完成。

于 2015-09-09T05:58:41.013 回答