限制 J2EE servlet 只能从本地主机调用的正确方法是什么?
What is the proper way to restrict a J2EE servlet to only be called from the localhost?
我正在构建一个 servlet 来执行只能从主机本身启动的工作。我目前的计划是检查服务方法中的请求对象:
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
我在 ServletRequest
上看到的唯一相关的方法是 getRemoteHost()
和 getRemoteAddr()
。我最大的担忧是这是否会被欺骗(有人可以使用源 IP 127.0.0.1
发送入站请求并启动该过程),或者如果正在使用 IPv6,根据 127.0.0.1
检查 IP 是否会失败。
会有一个凭证可以防止 IP 欺骗成功,但我不禁觉得有更好、更直接的方法来检查(或以其他方式限制)请求的来源。
是否有一种标准的方法可以可靠地进行这种独立于 IP 版本且不受欺骗的限制(假设攻击者可以获得凭据但无法访问服务器)?我认为从安全角度来看,凭据应该足够了;我最感兴趣的是 'right' 解决这个问题的方法是什么。
编辑:
我不认为这是 java- using a filter to check remote address 的重复,因为我一开始就没有考虑使用过滤器。虽然最终我采用了基于过滤器的解决方案,但这个问题也对其他潜在解决方案开放(例如,Raffaele 使用服务器套接字的建议可能对其他人有用,或者尚未发布的答案可能优于这两种方法)。
解决此问题的标准方法不是在 servlet(应用程序)级别执行操作,而是将整个服务器套接字绑定到 127.0.0.1
(或另一个环回地址)。
我认为 Java 服务器套接字的默认 API 使用 0.0.0.0
即 anyaddress,但是如果您指定一个环回地址,例如127.0.0.1
(或localhost
)您的应用程序在内核级别受到保护。
您可以使用 Filters
:
class OnlyLocalhostFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest.getLocalAddr().equals(servletRequest.getRemoteAddr())) {
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
}
}
之后声明您在 web.xml
中过滤 OnlyLocalhostFilter
并将其绑定到您想要的 servlet。
更新:
此解决方案并不总是有效。找到答案 here
我正在构建一个 servlet 来执行只能从主机本身启动的工作。我目前的计划是检查服务方法中的请求对象:
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
我在 ServletRequest
上看到的唯一相关的方法是 getRemoteHost()
和 getRemoteAddr()
。我最大的担忧是这是否会被欺骗(有人可以使用源 IP 127.0.0.1
发送入站请求并启动该过程),或者如果正在使用 IPv6,根据 127.0.0.1
检查 IP 是否会失败。
会有一个凭证可以防止 IP 欺骗成功,但我不禁觉得有更好、更直接的方法来检查(或以其他方式限制)请求的来源。
是否有一种标准的方法可以可靠地进行这种独立于 IP 版本且不受欺骗的限制(假设攻击者可以获得凭据但无法访问服务器)?我认为从安全角度来看,凭据应该足够了;我最感兴趣的是 'right' 解决这个问题的方法是什么。
编辑:
我不认为这是 java- using a filter to check remote address 的重复,因为我一开始就没有考虑使用过滤器。虽然最终我采用了基于过滤器的解决方案,但这个问题也对其他潜在解决方案开放(例如,Raffaele 使用服务器套接字的建议可能对其他人有用,或者尚未发布的答案可能优于这两种方法)。
解决此问题的标准方法不是在 servlet(应用程序)级别执行操作,而是将整个服务器套接字绑定到 127.0.0.1
(或另一个环回地址)。
我认为 Java 服务器套接字的默认 API 使用 0.0.0.0
即 anyaddress,但是如果您指定一个环回地址,例如127.0.0.1
(或localhost
)您的应用程序在内核级别受到保护。
您可以使用 Filters
:
class OnlyLocalhostFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest.getLocalAddr().equals(servletRequest.getRemoteAddr())) {
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
}
}
之后声明您在 web.xml
中过滤 OnlyLocalhostFilter
并将其绑定到您想要的 servlet。
更新:
此解决方案并不总是有效。找到答案 here