【问题标题】:How to get a reference to SessionAuthenticationStrategy without configuring the strategy explicit?如何在不显式配置策略的情况下获得对 SessionAuthenticationStrategy 的引用?
【发布时间】:2014-12-13 07:54:00
【问题描述】:

在基于 Spring Security 3.2 的应用程序中,我有一个显式配置的 UsernamePasswordAuthenticationFilter,需要引用 sessionAuthenticationStrategy(以便调用 .onAuthentication)。*

sessionAuthenticationStrategy<security:http> (HttpSecurityBeanDefinitionParser) 创建的默认值。

我的问题:我如何在不配置完整的 SessionAuthenticationStrategy 显式的情况下获得对 SessionAuthenticationStrategy 的引用,以便我可以在 XML 配置中注入此引用?

<security:http auto-config="false" use-expressions="true"
    entry-point-ref="loginUrlAuthenticationEntryPoint" 
    access-decision-manager-ref="httpAccessDecisionManager">
    ...
    <security:custom-filter
             ref="usernamePasswordAuthenticationFilter"
             position="FORM_LOGIN_FILTER"/>
    ...
</security:http>

...

<bean id="usernamePasswordAuthenticationFilter"
    class=" o.s.scurity.web.authentication.UsernamePasswordAuthenticationFilter">

   <property name="sessionAuthenticationStrategy" ref="????">   <!-- ?? ->
   ...
</bean>

*我真正的UsernamePasswordAuthenticationFilter 是一个自定义的子类,但这对于这个问题应该无关紧要

【问题讨论】:

标签: java spring spring-security


【解决方案1】:

我查看了负责解析security:http 标记和创建SessionAuthenticationStrategy bean 的类HttpSecurityBeanDefinitionParser(和HttpConfigurationBuilder.createSessionManagementFilters())。

因此,我知道 Spring Security 3.2.5.RELEASE 创建(在我的配置中)CompositeSessionAuthenticationStrategy bean 并将其用作会话策略。此 bean 将获得默认名称:org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy#0

所以我目前的解决方法是通过它的名称引用这个 bean:

<bean id="usernamePasswordAuthenticationFilter"
     class=" o.s.scurity.web.authentication.UsernamePasswordAuthenticationFilter">

    <property name="sessionAuthenticationStrategy">
        <ref
           bean="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy#0"/>                
    </property>
    ...
 </bean>

此解决方法有一些严重的限制:

  • 当新版本的 Spring Security 以其他方式工作(创建另一个 bean)时,它将失败。
  • 当有另一个 CompositeSessionAuthenticationStrategy 使用 ReaderContext.generateBeanName 创建名称时,此方法可能会失败,因为 #0 可能变为 #1(取决于创建 bean 的顺序)

【讨论】:

    【解决方案2】:

    恐怕没有明显的方法可以得到它。

    但是 Spring-Security 参考手册中的所有示例在这方面都是一致的:您甚至不应该想要得到它:所有示例都显示在 UserNamePasswordAuthenticationFilter 中注入的显式 SessionAuthenticationStrategy,如果合适,在 SessionManagementFilter 中注入。

    根据这2个类的javadocs,默认SessionAuthenticationStrategy是:

    • SessionFixationProtectionStrategy 用于 Servlet
    • ChangeSessionIdAuthenticationStrategy 用于 Servlet 3.1+

    所以正确的方法是创建一个实现SessionAuthenticationStrategy 的bean 实现上述默认值之一,或者如果您有特殊需要,则可以在任何需要的地方使用它。

    当然,总是可以使用反射来访问 Spring 安全实现类的私有成员,但你知道它不好并且在 Spring 安全的下一个版本中被破坏的风险很高.

    【讨论】:

    • 如何根据servlet容器中使用的servlet版本选择SessionAuthenticationStrategy impelementation?
    【解决方案3】:

    使用 JavaConfig 时(恐怕不是您的情况),您可以通过这样做来获得参考

            http.getConfigurer(SessionManagementConfigurer.class).init(http);
            http.getSharedObject(SessionAuthenticationStrategy.class);
    

    【讨论】:

      【解决方案4】:

      Ralph's answer 上展开,您可以使用FactoryBean 来获取对AuthenticationStrategy 的引用。

      public class SessionAuthenticationStrategyFactoryBean implements BeanFactoryAware, FactoryBean<SessionAuthenticationStrategy> {
      
          private BeanFactory beanFactory;
      
          @Override
          public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
              this.beanFactory = beanFactory;
          }
      
          @Override
          public SessionAuthenticationStrategy getObject() throws Exception {
              final CompositeSessionAuthenticationStrategy sas = beanFactory.getBean(CompositeSessionAuthenticationStrategy.class);
              return sas;
          }
      
          @Override
          public Class<?> getObjectType() {
              return SessionAuthenticationStrategy.class;
          }
      
          @Override
          public boolean isSingleton() {
              return true;
          }
      }
      

      ... 并使其在您的 XML 配置中可用:

      <bean id="sas" class="com.example.SessionAuthenticationStrategyFactoryBean" />
      
      <bean id="usernamePasswordAuthenticationFilter"
          class=" o.s.scurity.web.authentication.UsernamePasswordAuthenticationFilter">
      
         <property name="sessionAuthenticationStrategy" ref="sas">
         ...
      </bean>
      

      【讨论】:

        猜你喜欢
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 2020-06-25
        • 2015-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多