【问题标题】:Why is Spring Security working in Tomcat but not when deployed to Weblogic?为什么 Spring Security 在 Tomcat 中工作,但在部署到 Weblogic 时却没有?
【发布时间】:2015-06-06 04:57:22
【问题描述】:

我并不是真正的 Java 开发人员,但一个客户项目要求我这样做,所以我可能遗漏了一些明显的东西。

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

话虽如此。其他一切似乎都可以正常工作,只是根本没有任何安全措施。

我无权访问 Weblogic,因为客户端是部署代码的人,但他们告诉我们它在 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
    }

}

提前致谢。

【问题讨论】:

标签: java spring spring-security spring-boot weblogic12c


【解决方案1】:

听起来你好像遇到了SEC-2465。简而言之,WebLogic 中存在与添加 Filter 实例相关的 bug。从上面的JIRA:

Oracle 承认这是一个错误:17382048,已通过补丁 16769849 修复。 据报道已在 WLS 12.1.3 中修复

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

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

然后,您的 AbstractSecurityWebApplicationInitializer 子类将扩展您的自定义类。

更新

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

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

要解决此问题,您可以禁用 Spring Security 和任何其他过滤器的注册。您可以通过创建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 Security可以通过实现WebApplicationInitializer注册到上述机制。例如,您可以创建以下类:

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 将查找名为“springSecurityFilterChain”的 bean,并在每次调用 doFilter 时委托给它。

【讨论】:

  • 也许我遗漏了一些东西,但我没有在任何地方使用 AbstractSecurityWebApplicationInitializer。反正不是直接的。我不确定是否可以选择更新,所以我可能需要自己修复它。
  • 当您验证它在 Tomcat 中工作时,您是否将其部署为战争?
  • 是的,我将它部署为对 Tomcat 的战争,它可以完美地工作。部署到 Weblogic 后,一切都按预期工作,但没有任何安全措施,登录和注销路由不起作用。
  • 你是如何添加springSecurityFilterChain的?当使用嵌入式容器时(即使用可执行 jar 或可执行战争时),Spring Boot 会自动将 springSecurityFilterChain 映射为过滤器。但是,当部署为战争时,还有一些额外的步骤是必要的。您是否使用 web.xml 来映射它?
  • 我没有在任何地方添加 springSecurityFilterChain。不,我拥有的唯一与安全相关的代码在我的 Application.java 配置文件中。相关内容在我的代码块中。 FWIW,我正在使用 Spring Boot。
【解决方案2】:

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

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

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

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

【讨论】:

  • 已添加,但我仍然遇到同样的问题。
  • 由于应用程序使用 Spring Boot,所有过滤器都是使用 Java 配置创建的。这意味着 securityContextPersistenceFilter XML 定义不是必需的。
【解决方案3】:

为了记录,也许有点晚了,我最近遇到了同样的问题(以及其他问题)并使用 Spring MVC (4.1.1.RELEASE) 获得了 Spring Security (4.0.0.RELEASE)(不是 Spring Boot,所以不使用上面建议的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, "/*");

【讨论】:

    【解决方案4】:

    为了完整起见,如果您要部署到 Servlet 规范

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 2013-12-21
      • 2012-02-02
      • 1970-01-01
      • 2015-12-29
      • 2016-11-27
      相关资源
      最近更新 更多