使用 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
}
...
}
我想根据 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
}
...
}