将 Waffle Spring Security XML 配置迁移到 Spring Boot [英] Migrating a Waffle Spring Security XML configuration to Spring Boot

查看:58
本文介绍了将 Waffle Spring Security XML 配置迁移到 Spring Boot的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to use Waffle authentication with Spring Security, in a Spring Boot fashion. Expected result is 'block everything if Negotiate fails'.

Waffle 项目为此提供了一个配置示例一种用例(假设配置是通过 web.xml 完成的,如果 Negotiate 失败,则在此示例中回退到简单的 HTTP 身份验证,我不需要).但是尽管进行了多次尝试,我还是不明白如何使用 Boot 和 Java-only 配置将 Waffle 与 Spring Security 连接起来.我正在使用 Spring Boot 1.2.1.RELEASE 和 starters web 和 security,Waffle 版本是 1.7.3.

Waffle project provides a configuration example for this kind of use case (there is in this example a fallback to simple HTTP auth if Negotiate fails, which I don't need), assuming configuration is done through web.xml. But despite many attempts, I don't understand how to plug Waffle with Spring Security using Boot and Java-only configuration. I'm using Spring Boot 1.2.1.RELEASE with starters web and security, Waffle version is 1.7.3.

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

I realize that this is not a specific question but Spring forum now redirects here and Waffle guys don't know about Spring Boot. Could someone help me translate an XML Spring Security configuration to Spring Boot?

第一步是声明过滤器链和上下文加载器侦听器.

First step is declaring a filter chain and context loader listener.

<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 处理了,所以这里没有什么可做的.

I'm assuming (am I wrong?) that this is already handled by @EnableWebMvcSecurity, so nothing to do here.

接下来是声明几个提供者 bean,所以我翻译了这个

Next is declaring a couple of provider beans, so I translate this

<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 过滤器之前.

Final step is sec:http section configuration. An entry point is declared and filter is placed before BASIC auth filter.

示例:

<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 并成功,有时会因提供的令牌无效"错误(相同的凭据、用户、浏览器、配置)而导致协商过滤器崩溃.

Running this configuration leads to strange behavior: sometimes NTLM is triggered and succeed, sometimes Negotiate filter crashes with an 'invalid token supplied' error (same credentials, user, browser, configuration).

提供的示例就像一个魅力,让我觉得我的引导配置有问题.

Provided example works like a charm, which makes me think that my Boot configuration is in question.

感谢任何帮助!

推荐答案

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

Spring Boot auto-registers all Filter beans so in this case the NegotiateSecurityFilter ends up being twice in the filter chain.

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

You have to disable the auto-registration for this specific Filter by creating a FilterRegistrationBean overriding this behavior:

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

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

Also, as Dave Syer mentioned, you should be setting the authentication entry point bean using the ExceptionHandlingConfigurer.

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

这篇关于将 Waffle Spring Security XML 配置迁移到 Spring Boot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆