使用 application.properties 中的值初始化过滤器

Initializing filter with values from application.properties

我想根据 IP 地址保护我的 REST API (jersey2),但没有 Spring 安全等问题。我只需要将一些被授予完全访问权限的 IP 列入白名单。

为了实现这一点,我考虑将 IP 放入 application.properties 并使用过滤器强制执行限制。这在使用嵌入式 Jetty 服务器时工作得很好,但在 Tomcat.

上将应用程序部署为 war 时失败

我试图读取 Filter 构造函数和 init 方法中的属性(仅在代码段中显示的构造函数示例)。然而,在访问存储 IP 的 class 字段(字符串 ips)时,两者都会导致 NullPointerException。同样使用环境变量似乎也没有帮助。

感谢任何帮助。谢谢!

@Component("RestAuthFilter")
public class RestAuthFilter implements Filter {

    private String ips;

    public RestAuthFilter() {
        try {
            final Properties p;
            final InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties");
            p = new Properties();
            p.load(input);
            ips = p.getProperty("whitelist.rest.ips");
        } catch(IOException e) {
            ips = "127.0.0.1";
        }
    }

    @Override
    public void init(final FilterConfig config) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res,
                     final FilterChain chain) throws ServletException,     IOException {

        final List<String> allowedIPs = Arrays.asList(ips.split("[,]"));

        if(!allowedIPs.contains(req.getRemoteAddr())) {
            ((HttpServletResponse) res).setStatus(HttpServletResponse.SC_FORBIDDEN, "Not allowed to use REST API!");
        } else {
            chain.doFilter(req, res);
       }
    }

    @Override
   public void destroy() {
   }

}

堆栈跟踪:

java.lang.NullPointerException: null
    at com.example.RestAuthFilter.doFilter(RestAuthFilter.java:44)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:113)
    at org.springframework.boot.context.web.ErrorPageFilter.access[=12=]0(ErrorPageFilter.java:59)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilterInternal(ErrorPageFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:106)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

由于您使用的是 Spring 引导并且您的设置非常标准,我会坚持使用 PropertySource(通过 @Value 或环境)从 application.properties 加载 IP。话虽如此,并注意到您对使用环境的评论...

Concerning to the Environment variable I am refering to org.springframework.core.env.Environment, which I included using DI, something like @Autowired Environment env as class member

您不能将其作为 class 成员注入并在构造函数中进行初始化,您将 运行 陷入范围问题——当构造函数是叫。您需要通过构造函数而不是 class 成员注入环境,例如:

@Component("RestAuthFilter")
public class RestAuthFilter implements Filter {

  private final List<String> restClientIps;

  @Autowired
  public RestAuthFilter(Environment env) {
    String restClientIpsProperty = env.getRequiredProperty("whitelist.rest.ips");
    restClientIps = // parse/split from restClientIpsProperty
  }
  ...
}