为什么 Spring 安全性在 Tomcat 中起作用,但在部署到 Weblogic 时却不起作用?

Why is Spring Security working in Tomcat but not when deployed to Weblogic?

我不是真正的 Java 开发人员,但客户的项目要求我成为,所以我可能遗漏了一些非常明显的东西。

我正在使用 SpringBoot,当应用程序在 Tomcat 在我的本地计算机和我们的测试服务器上运行时,一切正常。但是,一旦将应用程序部署到 Weblogic,就好像所有路由都可以访问一样完全没有安全性。登录和注销路由也不存在。

话虽这么说。其他一切似乎都工作正常,只是根本没有任何安全措施。

我无法访问 Weblogic,因为客户端是部署代码的那个,但他们告诉我们它是 运行 on 12c。我该怎么做才能修复或解决此问题?

这是我的 Application.java 的相关配置:

/**
 * The type Authentication security.
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {

    /**
     * The Users.
     */
    @Autowired
    private Users users;

    /**
     * Init void.
     *
     * @param auth the auth
     * @throws Exception the exception
     */
    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(users).passwordEncoder(new BCryptPasswordEncoder());
    }
}

/**
 * The type Application security.
 */
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    /**
     * Configure void.
     *
     * @param http the http
     * @throws Exception the exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.authorizeRequests()
                .antMatchers("/vendor/*","/public/**/*","/partners/*","/events/*", "/login").permitAll()
                .anyRequest().fullyAuthenticated().and().formLogin().loginPage("/login")
                .and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).and()
                .exceptionHandling().accessDeniedPage("/access?error");
        // @formatter:on
    }

}

提前致谢。

我认为您需要在过滤器链中添加 securityContextPersistenceFilter

<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />

我在 SecurityContextPersistenceFilter class 中发现了以下注释:

 * This filter will only execute once per request, to resolve servlet container (specifically Weblogic)
 * incompatibilities.

听起来您好像 运行 变成了 SEC-2465。简而言之,WebLogic 中存在与添加 Filter 实例相关的错误。来自上面的 JIRA:

Oracle acknowledged it as a bug: 17382048, fixed with patch 16769849. It is reported as being fixed in WLS 12.1.3

客户端应更新其 WebLogic 服务器以获得修复。或者,您可以创建自己的 AbstractSecurityWebApplicationInitializer 版本,使用 class 方法注册 springSecurityFilterChain:

servletContext.addFilter(String filterName, java.lang.Class<? extends Filter> filterClass)

您的 AbstractSecurityWebApplicationInitializer 的子class 将改为扩展您的自定义 class。

更新

根据更新的信息,我仍然认为问题与上述 WebLogic 错误有关。当使用 SpringBootServletInitializer 时,过滤器以 FilterRegistrationBean 作为实例而不是 class.

添加

最简单的选择是更新到 WebLogic,因为一切都应该按原样运行。

要解决此问题,您可以禁用 Spring 安全和任何其他过滤器的注册。您可以通过创建如下所示的 FilterRegistrationBean 来做到这一点:

@Bean
public FilterRegistrationBean springSecurityFilterChainRegistrationBean(@Qualifier("springSecurityFilterChain") Filter filter) {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(filter);
    bean.setEnabled(false);
    return bean;
}

然后您需要确保使用

注册过滤器
servletContext.addFilter(String filterName, java.lang.Class<? extends Filter> filterClass)

Spring 可以通过实现WebApplicationInitializer 向上述机制注册安全性。例如,您可以创建以下 class:

package demo;

import java.util.EnumSet;

import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.*;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.filter.DelegatingFilterProxy;

public class SecurityInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext context) throws ServletException {
        Dynamic registration =
                context.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
        EnumSet<DispatcherType> dispatcherTypes =
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
        registration.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
    }
}

DelegatingFilterProxy 将在每次调用 doFilter 时查找名称为 "springSecurityFilterChain" 的 bean 并委托给它。

郑重声明,也许有点晚了,我最近 运行 遇到了同样的问题(除其他外),并使用 [=18] 获得了 Spring 安全性 (4.0.0.RELEASE) =] MVC (4.1.1.RELEASE)(不是 Spring 引导,因此不使用上面提到的 FilterRegistrationBean)在 Weblogic 12.1.3 上工作。感谢 Rob Winch 添加了 Filterchain(解决了所有 url 都可以在不安全的情况下访问的问题)。 实现 WebApplicationInitializer 并覆盖 onStart 方法,如下所示:

    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(SecurityConfiguration.class);

    // Manage the lifecycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));

    // Create the dispatcher servlet's Spring application context
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
    dispatcherServlet.register(WebMvcConfiguration.class);

    // Register and map the dispatcher servlet
    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");

    // Register spring security FilterChain
    FilterRegistration.Dynamic registration = container.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
    EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
    registration.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

为了完整起见,如果您要部署到 Servlet 规范 < 3.0 的旧版本 Weblogic(例如 10.3.6 和 2.5),那么您需要在 web.xml 中定义 springSecurityFilterChain:

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