将 Waffle Spring Security XML 配置迁移到 Spring Boot

Posted

技术标签:

【中文标题】将 Waffle Spring Security XML 配置迁移到 Spring Boot【英文标题】:Migrating a Waffle Spring Security XML configuration to Spring Boot 【发布时间】:2015-04-10 12:40:43 【问题描述】:

我正在尝试以 Spring Boot 方式将 Waffle 身份验证与 Spring Security 一起使用。预期结果是“如果协商失败,则阻止一切”。

Waffle 项目为这种用例提供​​了一个configuration example(在此示例中,如果协商失败,则回退到简单的 HTTP 身份验证,我不需要),假设配置是通过web.xml 完成的。但是,尽管进行了多次尝试,但我不明白如何使用 Boot 和纯 Java 配置将 Waffle 与 Spring Security 相结合。我正在使用 Spring Boot 1.2.1.RELEASE 和启动器 web 和安全性,Waffle 版本是 1.7.3。

我意识到这不是一个特定的问题,但 Spring 论坛现在重定向到这里,Waffle 的人不知道 Spring Boot。有人可以帮我将 XML Spring Security 配置转换为 Spring Boot 吗?

第一步是声明一个过滤器链和上下文加载监听器。

<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>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/waffle-filter.xml</param-value> 
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

我假设(我错了吗?)这已经由 @EnableWebMvcSecurity 处理,所以这里无事可做。

接下来是声明几个provider beans,所以我翻译一下

<bean id="waffleWindowsAuthProvider" class="waffle.windows.auth.impl.WindowsAuthProviderImpl" />

<bean id="negotiateSecurityFilterProvider" class="waffle.servlet.spi.NegotiateSecurityFilterProvider">
    <constructor-arg ref="waffleWindowsAuthProvider" />
</bean>

<bean id="basicSecurityFilterProvider" class="waffle.servlet.spi.BasicSecurityFilterProvider">
    <constructor-arg ref="waffleWindowsAuthProvider" />
</bean>

<bean id="waffleSecurityFilterProviderCollection" class="waffle.servlet.spi.SecurityFilterProviderCollection">
    <constructor-arg>
        <list>
            <ref bean="negotiateSecurityFilterProvider" />               
            <ref bean="basicSecurityFilterProvider" />               
        </list>
    </constructor-arg>
</bean>

<bean id="waffleNegotiateSecurityFilter" class="waffle.spring.NegotiateSecurityFilter">
    <property name="Provider" ref="waffleSecurityFilterProviderCollection" />
</bean>

到这里

@Bean
public WindowsAuthProviderImpl waffleWindowsAuthProvider() 
    return new WindowsAuthProviderImpl();


@Bean
@Autowired
public NegotiateSecurityFilterProvider negotiateSecurityFilterProvider(final WindowsAuthProviderImpl windowsAuthProvider) 
    return new NegotiateSecurityFilterProvider(windowsAuthProvider);


@Bean
@Autowired
public BasicSecurityFilterProvider basicSecurityFilterProvider(final WindowsAuthProviderImpl windowsAuthProvider) 
    return new BasicSecurityFilterProvider(windowsAuthProvider);


@Bean
@Autowired
public SecurityFilterProviderCollection waffleSecurityFilterProviderCollection(final NegotiateSecurityFilterProvider negotiateSecurityFilterProvider, final BasicSecurityFilterProvider basicSecurityFilterProvider) 
    final SecurityFilterProvider[] securityFilterProviders = 
            negotiateSecurityFilterProvider,
            basicSecurityFilterProvider
    ;
    return new SecurityFilterProviderCollection(securityFilterProviders);


@Bean
@Autowired
public NegotiateSecurityFilter waffleNegotiateSecurityFilter(final SecurityFilterProviderCollection securityFilterProviderCollection) 
    final NegotiateSecurityFilter negotiateSecurityFilter = new NegotiateSecurityFilter();
    negotiateSecurityFilter.setProvider(securityFilterProviderCollection);
    return negotiateSecurityFilter;

最后一步是sec:http 部分配置。声明了一个入口点,并将过滤器放置在 BASIC auth 过滤器之前。

例子:

<sec:http entry-point-ref="negotiateSecurityFilterEntryPoint">
    <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
    <sec:custom-filter ref="waffleNegotiateSecurityFilter" position="BASIC_AUTH_FILTER" />
</sec:http>

<bean id="negotiateSecurityFilterEntryPoint" class="waffle.spring.NegotiateSecurityFilterEntryPoint">
    <property name="Provider" ref="waffleSecurityFilterProviderCollection" />
</bean>

我的开机翻译:

@Autowired
private NegotiateSecurityFilterEntryPoint authenticationEntryPoint;

@Autowired
private NegotiateSecurityFilter negotiateSecurityFilter;    

@Override
protected void configure(final HttpSecurity http) throws Exception 
    http
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .addFilterBefore(this.negotiateSecurityFilter, BasicAuthenticationFilter.class)
            .httpBasic().authenticationEntryPoint(this.authenticationEntryPoint);


@Bean
@Autowired
public NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint(final SecurityFilterProviderCollection securityFilterProviderCollection) 
    final NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint = new NegotiateSecurityFilterEntryPoint();
    negotiateSecurityFilterEntryPoint.setProvider(securityFilterProviderCollection);
    return negotiateSecurityFilterEntryPoint;

运行此配置会导致奇怪的行为:有时 NTLM 被触发并成功,有时 Negotiate 过滤器崩溃并出现“提供的令牌无效”错误(相同的凭据、用户、浏览器、配置)。

Provided example 就像一个魅力,让我觉得我的引导配置有问题。

任何帮助表示赞赏!

【问题讨论】:

如果过滤器触发,我想它一定在工作。我真的对华夫饼一无所知(但它看起来很有趣)。我发现您的代码和 XML 示例的一个区别是您仅将自定义入口点安装到 HTTP 基本过滤器中(而不是整个链的异常处理)。可能你需要这样做,但我不知道它是否能解决所有问题。 感谢您的反馈。它不能解决“无效令牌”问题(为此我会再次 ping Waffle 团队),但这是一个开始。 这方面有什么更新吗?我有同样的问题(我认为)。 Spring Boot 上的华夫饼。它在 Chrome 和其他浏览器中似乎可以正常工作,但在使用 IE11 时会失败。服务器记录一个 Win32Exception “提供给函数的令牌无效” 我不再处理这个问题,但我很乐意了解更多相关信息。如果您发现有用的东西请告诉我,我想如果需要我可以做一些测试。 【参考方案1】:

Spring Boot 会自动注册所有过滤器 bean,因此在这种情况下,NegotiateSecurityFilter 最终会在过滤器链中出现两次。

您必须通过创建一个覆盖此行为的 FilterRegistrationBean 来禁用此特定过滤器的自动注册:

@Bean
public FilterRegistrationBean registration(NegotiateSecurityFilter filter) 
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;

此外,正如 Dave Syer 所提到的,您应该使用 ExceptionHandlingConfigurer 设置身份验证入口点 bean。

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint);
    // ...

【讨论】:

感谢您的澄清!不幸的是,我不再使用 Waffle 进行任何项目,因此我无法测试您的提案。如果有人可以试一试并告诉我们,我很乐意批准您的回答。 是的!这对我有用(Spring Boot 2.2 + Waffle 2.2.1)

以上是关于将 Waffle Spring Security XML 配置迁移到 Spring Boot的主要内容,如果未能解决你的问题,请参考以下文章

集成 Windows 身份验证 spring 安全性

JCIFS NTLM 库的替代品

使用 @nomiclabs/hardhat-waffle 实现夹具

Spring Security:如何将两个应用程序与单独的 Spring Security 配置集成?

如何使用 Spring-Security 3 和 Hibernate 4 将 spring security xml 配置 hibernate 转换为 java config

Solidity:使用 waffle + chai 测试恢复的断言不起作用