Spring security 打开和关闭spring security SAML的方法

Spring security 打开和关闭spring security SAML的方法,spring-security,spring-saml,Spring Security,Spring Saml,除了其他身份验证机制之外,我的应用程序中还有一个相当标准的spring security saml实现。开箱即用SAML将不会被配置,但可以通过表单进行配置,因此默认情况下应禁用SAML。我希望能够轻松地打开/关闭SAML,但不确定最好的方法是什么 一种方法似乎是执行自定义FilterChainProxy,如果我检查saml是否启用,如果启用,则忽略samlFilter chain(),并对元数据生成器过滤器执行类似的实现 任何建议都很好 这是我的配置: <http auto-config

除了其他身份验证机制之外,我的应用程序中还有一个相当标准的spring security saml实现。开箱即用SAML将不会被配置,但可以通过表单进行配置,因此默认情况下应禁用SAML。我希望能够轻松地打开/关闭SAML,但不确定最好的方法是什么

一种方法似乎是执行自定义FilterChainProxy,如果我检查saml是否启用,如果启用,则忽略samlFilter chain(),并对元数据生成器过滤器执行类似的实现

任何建议都很好

这是我的配置:

<http auto-config="false" use-expressions="true"
      access-decision-manager-ref="webAccessDecisionManager"
      disable-url-rewriting="false"
      create-session="never"
      authentication-manager-ref="authenticationManager">

    <custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
    <custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</http>
还有自动连线的samlFilter/FilterChainMap。如果启用saml,我将保持此链的原样,如果禁用,我将在我的服务中将该链设置为空映射,以启用/禁用saml

初始化后,我获得filterchainmap值:

private Map<RequestMatcher, List<Filter>> map;

@Override
public void init() throws ServiceException, MetadataProviderException {

    SamlConfig samlConfig = getConfig();
    map = samlFilter.getFilterChainMap();

    applySamlConfig(samlConfig);

}
私有地图;
@凌驾
public void init()引发ServiceException,MetadataProviderException{
SamlConfig SamlConfig=getConfig();
map=samlFilter.getFilterChainMap();
applySamlConfig(samlConfig);
}
在下面的方法中,我将过滤器链映射设置为SpringXML中提供的原始映射(如果启用)或空映射(如果禁用)

public void applySamlConfig(SamlConfig SamlConfig)引发ServiceException、MetadataProviderException{
如果(!samlConfig.isEnabled()){
Map emptyMap=samlFilter.getFilterChainMap();
清空映射清除();
samlFilter.setFilterChainMap(清空映射);
返回;
}
samlFilter.setFilterChainMap(map);

到目前为止,我一直在使用一个定制的Spring名称空间来实现这一点,该名称空间包括或跳过基于后端配置的某些bean,并在后端配置更改时重新加载Spring上下文。

编辑:修复了Turkish发出的错误信号

如果您希望能够在运行的应用程序上切换SAML的使用,更简单的方法是在samlFilter周围使用包装器

public class FilterWrapper extends GenericFilterBean {

    private Filter inner;
    private boolean active;
    private boolean targetFilterLifeCycle = false;


    public Filter getInner() {
        return inner;
    }

    public void setInner(Filter inner) {
        this.inner = inner;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    @Override
    public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
        if (active) {
            inner.doFilter(sr, sr1, fc);
        }
        else {
            fc.doFilter(str,sr1);
        }
    }

    @Override
    protected void initFilterBean() throws ServletException {
        super.initFilterBean();
        if (inner == null) {
            throw new ServletException("Inner cannot be null");
        }
        if (targetFilterLifeCycle) {
            inner.init(getFilterConfig());
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        if (inner != null && targetFilterLifeCycle) {
            inner.destroy();
        }
    }
}
您可以这样使用它:

<bean id="samlFilter" class="...FilterWrapper" p:active="false">
    <property name=inner>
        <!-- the real samlFilter bean -->
        <bean class="org.springframework.security.web.FilterChainProxy">
        ...
        </bean>
    </property>
</bean>

我在入口点参考定义中添加了一个自定义过滤器。如果该功能未启用,该过滤器将跳过所有以下过滤器

<security:http entry-point-ref="samlEntryPoint">
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <!-- This filter checks if the SSO-Feature is enabled - otherwise all following security filters will be skipped -->
  <security:custom-filter before="BASIC_AUTH_FILTER" ref="ssoEnabledFilter"/>
  <security:custom-filter before="FIRST" ref="metadataGeneratorFilter" />
  <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter" />

您是否计划在实时应用程序上执行此操作,或者您有能力更改设置并重新启动服务器?@dharam,理想情况下,您不必重新启动,但必须重新启动是可以接受的。@TheTurkish。您解决了此问题吗?现在,我想要与您期望的相同的行为,但我使用的是注释而不是xml,您可以吗让我知道你是如何解决这个问题的?嗯。这似乎不起作用。它看起来像是inner.doFilter(sr,sr1,fc);未被调用,筛选器将被完全终止,应用程序不会返回响应。您可以分享实现的详细信息,或者让我了解有关自定义Spring命名空间的其他信息吗?我猜这需要重新启动应用程序吗?这里有一些教程:,它不需要重新启动,因为您可以调用ApplicationContext.refresh()这将重新加载您的bean。但我相信,如果您只想启用/禁用过滤器,还有更简单的方法。自定义名称空间允许对整个Spring SAML进行更动态的配置,而不仅仅是启用/禁用。但实现起来需要时间。我在@David处尝试了上述解决方案,最后出现了以下错误org.apache.catalina.core、 Servlet[default]的ApplicationDispatcher.invoke Servlet.service()引发异常java.lang.StackOverflower请求处理期间,问题似乎与无限过滤有关。
http.httpBasic().authenticationEntryPoint(SamlentPoint());http.addFilterBefore(CheckSAMLConf(),BasicAuthenticationFilter.class);http.addFilterBefore(metadataGeneratorFilter(),ChannelProcessingFilter.class);http.addFilterAfter(springSecurityFilter(),BasicAuthenticationFilter.class);
类SSEnabledFilter扩展了GenericFilterBean{@Override public void doFilter(final ServletRequest请求,final ServletResponse响应,final FilterChain FilterChain)抛出IOException,ServletException{boolean ssoEnabled=false;if(ssoEnabled){FilterChain.doFilter(请求,响应);}else{request.getRequestDispatcher((HttpServletRequest)请求).getServletPath()).forward(请求、响应);}}}
public void applySamlConfig(SamlConfig samlConfig) throws ServiceException, MetadataProviderException {


    if (!samlConfig.isEnabled()) {
        Map<RequestMatcher, List<Filter>> emptyMap = samlFilter.getFilterChainMap();
        emptyMap.clear();
        samlFilter.setFilterChainMap(emptyMap);
        return;
    }

    samlFilter.setFilterChainMap(map);
public class FilterWrapper extends GenericFilterBean {

    private Filter inner;
    private boolean active;
    private boolean targetFilterLifeCycle = false;


    public Filter getInner() {
        return inner;
    }

    public void setInner(Filter inner) {
        this.inner = inner;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    @Override
    public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
        if (active) {
            inner.doFilter(sr, sr1, fc);
        }
        else {
            fc.doFilter(str,sr1);
        }
    }

    @Override
    protected void initFilterBean() throws ServletException {
        super.initFilterBean();
        if (inner == null) {
            throw new ServletException("Inner cannot be null");
        }
        if (targetFilterLifeCycle) {
            inner.init(getFilterConfig());
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        if (inner != null && targetFilterLifeCycle) {
            inner.destroy();
        }
    }
}
<bean id="samlFilter" class="...FilterWrapper" p:active="false">
    <property name=inner>
        <!-- the real samlFilter bean -->
        <bean class="org.springframework.security.web.FilterChainProxy">
        ...
        </bean>
    </property>
</bean>
samlFilter.setActive(active);
<security:http entry-point-ref="samlEntryPoint">
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <!-- This filter checks if the SSO-Feature is enabled - otherwise all following security filters will be skipped -->
  <security:custom-filter before="BASIC_AUTH_FILTER" ref="ssoEnabledFilter"/>
  <security:custom-filter before="FIRST" ref="metadataGeneratorFilter" />
  <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter" />
    public class SsoEnabledFilter extends GenericFilterBean {

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
        boolean ssoEnabled = isSsoEnabled();

        if (ssoEnabled) {
            filterChain.doFilter(request, response);
        } else {
            request.getRequestDispatcher(((HttpServletRequest) request).getServletPath()).forward(request, response);
        }
      }
   }