如何在Spring Security中使用Spring DelegatingFilterProxy来处理多个过滤器?

3
我们正在使用使用初始化为AbstractSecurityWebApplicationInitializer的Spring安全性。我们还有一个单独的Web应用程序初始化器,它从AbstractAnnotationConfigDispatcherServletInitializer扩展。我将后者设置为@Order(Ordered.HIGHEST_PRECEDENCE),如前面所建议的那样。到目前为止都很好。

现在我想引入其他Servlet过滤器,这些过滤器与Spring安全性无关,因此应该单独配置。我知道可以使用DelegatingFilterProxy将请求委派给过滤器。但是,DelegatingFilterProxy没有接受多个过滤器的功能。一种选择是定义自定义FilterChain,就像Spring安全性中做的那样FilterChainProxy。这仍然会创建2个DelegatingFilterProxy,而且我明白应该在应用中只有一个DelegatingFilterProxy

有什么想法吗?

1个回答

0
回答自己的问题,这是我做的方法:
我对AbstractAnnotationConfigDispatcherServletInitializer进行了子类化,在其中:
/**
     * {@inheritDoc}
     */
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] { requestContextFilter(), teFilterChain() };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected FilterRegistration.Dynamic registerServletFilter(
            ServletContext servletContext, Filter filter) {
        String filterName = Conventions.getVariableName(filter);
        Dynamic registration = servletContext.addFilter(filterName, filter);
        if (registration == null) {
            int counter = -1;
            while (counter == -1 || registration == null) {
                counter++;
                registration = servletContext
                        .addFilter(filterName + "#" + counter, filter);
                Assert.isTrue(counter < 100, "Failed to register filter '"
                        + filter + "'."
                        + "Could the same Filter instance have been registered already?");
            }
        }
        registration.setAsyncSupported(isAsyncSupported());

        registration.addMappingForServletNames(getDispatcherTypes(), false,
                getServletName());
        return registration;
    }

    /**
     * Spring, by default, registers filters for 'FORWARD' dispatcher type as
     * well which causes TE filter chain to run again after Spring security
     * successfully authenticates and forwards the incoming request. We thus
     * exclude 'FORWARD' dispatcher type.
     */
    private EnumSet<DispatcherType> getDispatcherTypes() {
        return (isAsyncSupported()
                ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.INCLUDE,
                        DispatcherType.ASYNC)
                : EnumSet.of(DispatcherType.REQUEST, DispatcherType.INCLUDE));
    }

    private Filter requestContextFilter() {
        return new DelegatingFilterProxy(TE_REQ_CTX_FILTER);
    }

    private Filter teFilterChain() {
        return new DelegatingFilterProxy(TE_FILTER_CHAIN);
    }

    @Override
    protected void registerDispatcherServlet(ServletContext ctx) {
        super.registerDispatcherServlet(ctx);

        registerSpringSecurityFilter(ctx);
        registerCorsFilter(ctx);
    }

    @Override
    protected DispatcherServlet createDispatcherServlet(
            WebApplicationContext servletAppContext) {
        DispatcherServlet servlet = new DispatcherServlet(servletAppContext);
        servlet.setThreadContextInheritable(true);
        servlet.setThrowExceptionIfNoHandlerFound(true);

        return servlet;
    }

    private Dynamic registerCorsFilter(ServletContext ctx) {
        Dynamic registration = ctx.addFilter("CorsFilter", CorsFilter.class);

        registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_ORIGINS,
                CORS_ALLOWED_ORIGINS);
        registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_METHODS,
                CORS_ALLOWED_METHODS);
        registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_HEADERS,
                CORS_ALLOWED_HEADERS);

        registration.addMappingForUrlPatterns(getDispatcherTypes(), false,
                "/*");

        return registration;
    }

    @Override
    protected boolean isAsyncSupported() {
        return true;
    }

    private final FilterRegistration.Dynamic registerSpringSecurityFilter(
            ServletContext servletContext) {
        FilterRegistration.Dynamic registration = servletContext.addFilter(
                SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain());

        if (registration == null) {
            throw new IllegalStateException("Duplicate Filter registration for "
                    + SPRING_SECURITY_FILTER_CHAIN
                    + "'. Check to ensure the Filter is only configured once.");
        }

        registration.setAsyncSupported(isAsyncSupported());
        EnumSet<DispatcherType> dispatcherTypes = getSecurityDispatcherTypes();
        /*
         * Don't use URL mapping for registering Spring security because then
         * the chain will kick in before DispatcherServlet.
         */
        registration.addMappingForServletNames(dispatcherTypes, true,
                getServletName());

        return registration;
    }

    private Filter springSecurityFilterChain() {
        return new DelegatingFilterProxy(SPRING_SECURITY_FILTER_CHAIN);
    }

    protected EnumSet<DispatcherType> getSecurityDispatcherTypes() {
        return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR,
                DispatcherType.ASYNC);
    }

你不能使用FilterChainProxy吗? - lqbweb
@lqbweb 三年半后,我不记得了。 - Abhijit Sarkar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接