doFilter方法在自定义Servlet过滤器中引发错误时多次调用

问题描述 投票:0回答:1

我已经实现了一个过滤器,以使用Spring Security检查IP地址白名单。它可以工作,但是如果我在doFilter方法中抛出错误,则该抛出被称为3次oO。

我找到了一个带有“ return;”的解决方案,但是我对此并不满意。这意味着我必须在不使用throw的情况下记录我的错误...

您认为,还有什么更好的方法吗?最佳做法?

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

这是Web配置

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                        .antMatchers("/**").permitAll().and()
                        .addFilterBefore(new CustomIpFilter(),
                                BasicAuthenticationFilter.class)
                        .csrf().disable()
                        .formLogin().disable();
        }
    }

这是我的过滤器

    @Log4j2
    @WebFilter
    public class CustomIpFilter implements Filter {

        Set<String> whitelist = new HashSet<>();

        public CustomIpFilter() {
            whitelist.add("0:0:0:0:0:0:0:1"); //localhost
            whitelist.add("127.0.0.1");
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {

            String ipAdress = request.getRemoteAddr();
            if (!whitelist.contains(ipAdress)) {
                log.error("Unknown IP adress");
                /* if the return is replaced by throw line, it still works, but doFilter will be called 3 times and throw 3 times the same error
                throw new UnknownHostException("Unknown IP adress");*/
                return;
            }
            chain.doFilter(request, response); //Continue
        }

        @Override
        public void destroy() {

        }

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {

        }
    }

用于测试的控制器

@RestController
@RequestMapping(value = "test")
public class LoggerController {

    @GetMapping("/go")
    public String logsTest() {
        System.out.println("ok");
        return "Ok";
    }
}

我已经尝试过使用拦截器使用“ preHandle”方法删除Spring Security的相同内容,但我仍然拥有3倍的Throw。因此,我开始理解为什么,请查看日志:

第一掷

java.net.UnknownHostException: Unknown IP adress

第二掷

[nio-8181-exec-5] c.e.d.S.IpAdressInterceptor              : Unknown IP adress
[nio-8181-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] threw exception

第三掷:

[nio-8181-exec-5] o.a.c.c.C.[Tomcat].[localhost]           : Exception Processing ErrorPage[errorCode=0, location=/error]

感谢您的帮助!

java spring security servlets filter
1个回答
0
投票

您正在Servlet环境中运行。 Servlet规范没有说您应该通过抛出异常来响应错误。相反,您应该使用HTTP状态代码和消息进行响应。当您引发异常时,servlet容器将尽最大努力弄清楚该怎么做,但经常会导致向用户返回500 Internal Server Error,这是不准确或无用的。

仅从过滤器返回也是不正确的,因为您没有在HTTP响应中添加任何内容。同样,您应该在响应中设置适当的状态代码,例如“ 403禁止访问”,它可以向呼叫者指示未正确配置某些内容。

© www.soinside.com 2019 - 2024. All rights reserved.