【问题标题】:How to use Spring Session + Spring security xml configuration and multiply security filter如何使用 Spring Session + Spring security xml 配置和多重安全过滤器
【发布时间】:2015-12-04 05:35:58
【问题描述】:

背景

大家好, 我们有使用Spring securitySpring 项目。我们通过定义来定义安全过滤器

 <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>

这一切都很好:)。现在,当根据doc 连接Spring sessionredis 时,接下来的几行

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

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

<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 />

结果:该应用似乎运行良好,并且通过redis-climonitoring 显示spring 正在与redis 通信。

问题

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

谢谢,

橡木

编辑

似乎上述方法不适用于想要从代码中Authenticate 用户的情况,即

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

将失败。可能是因为它不足以通过filter-chainorg.springframework.security.web.FilterChainProxy 运行它。

你觉得在web.xml 中以filter 运行它会怎样?

<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>

以上将强制在springSecurityFilterChain 之前运行springSessionRepositoryFilter,但在此示例中org.springframework.web.filter.DelegatingFilterProxy 被调用两次。还有其他方法可以让springSessionRepositoryFilterspringSecurityFilterChain 过滤器之前作为过滤器运行吗?

【问题讨论】:

  • 我知道这是一个老问题。 bu 你找到解决这个问题的方法了吗?我目前面临同样的问题
  • 这个确实老问题,我想我可以看看答案。你还需要吗?
  • 您好,谢谢您的回复。我们暂时从项目中删除了 spring-session,因为我们无法解决这个问题。如果花费太多时间,您不必搜索答案
  • 嘿,我添加了对这个问题的回答。希望它可以帮助您解决问题

标签: spring-security spring-session spring-data-redis


【解决方案1】:

根据我的测试,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 支持。 source

现在,由于我们有名为 springSessionRepositoryFiltersession filter,它必须作为第一个过滤器运行,因为它替换了 HttpSession 实现。

为此,我们将其声明为web.xml 中的第一个过滤器。有关过滤器和过滤器订单的更多信息,请查看docs

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。 reference

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

reference

【讨论】:

  • 感谢您的回答。我现在有一个类似的设置,但我们仍然有一些请求的问题。你认为两个 DelegatingFilterProxy 会不会有问题?
【解决方案2】:

没关系。来自Javadoc

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

只要在可以提交响应或访问HttpSession 的任何内容之前添加springSessionRepositoryFilter,就可以了。对于 Spring Security,您要确保的主要内容是 springSessionRepositoryFilterSecurityContextPersistenceFilter 之前。这可以通过在容器中或 Spring Security 的 FilterChainProxy(即 &lt;filter-chain&gt;)中包含 springSessionRepositoryFilter 来完成。

【讨论】:

  • 您好,感谢您的回复。上面的解决方案提出了一些问题。例如,尝试从代码中执行 SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); 似乎无法运行。我的想法是,即使这个过滤器通过&lt;filter-chain&gt; 设置为第一个过滤器,它仍然不够,应该在它之前运行。你怎么看?
猜你喜欢
  • 2018-02-09
  • 2018-01-31
  • 1970-01-01
  • 2015-07-23
  • 2018-08-05
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
相关资源
最近更新 更多