如何在Jetty 10.0.12中判断Servlet请求是否为内部请求?
嵌入式Jetty 10.0.12内部API请求过滤实现
针对你的需求,这里提供几个可靠的方案来判断请求是否来自同一JVM内的其他Servlet:
方案一:自定义内部请求标记(最可靠)
核心思路是让内部发起请求的Servlet在调用内部API时,添加一个只有内部系统知道的自定义属性,Filter通过检查这个属性来放行请求。
修改Filter代码:
import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class InternalFilter implements Filter { // 自定义内部标记的属性名,建议用唯一的包名前缀避免冲突 private static final String INTERNAL_REQUEST_MARKER = "com.yourcompany.internal.request"; @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { // 检查是否存在内部请求标记 if (Boolean.TRUE.equals(request.getAttribute(INTERNAL_REQUEST_MARKER))) { chain.doFilter(request, response); return; } // 非内部请求,返回403禁止访问 HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.sendError(HttpServletResponse.SC_FORBIDDEN, "Internal API only"); } }
内部Servlet调用示例:
当其他内部Servlet需要访问这个API时,通过RequestDispatcher转发或包含请求,并添加标记:
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class SomeInternalServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { // 添加内部请求标记 req.setAttribute(InternalFilter.INTERNAL_REQUEST_MARKER, true); // 转发到内部API Servlet req.getRequestDispatcher("/internal-api-path").forward(req, resp); } }
方案二:利用Jetty内部请求标识
Jetty的org.eclipse.jetty.server.Request类提供了判断内部分发的方法,当请求是通过RequestDispatcher转发/包含(同一JVM内)时,会被标记为内部请求。
修改Filter代码:
import org.eclipse.jetty.server.Request; import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class InternalFilter implements Filter { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { // 将ServletRequest转换为Jetty的Request对象 if (request instanceof Request jettyRequest) { // 判断是否是内部分发请求(转发/包含) if (jettyRequest.isInternalDispatch()) { chain.doFilter(request, response); return; } } // 非内部请求,返回403 HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.sendError(HttpServletResponse.SC_FORBIDDEN, "Internal API only"); } }
注意:这个方法仅适用于通过
RequestDispatcher发起的内部请求,如果你是通过HTTP客户端直接调用(即使是同一JVM内的HTTP客户端),不会被标记为内部分发,此时需要用方案一。
方案三:检查请求来源地址(局限性较大)
如果你的内部API仅允许本地回环地址访问,可以检查请求的远程地址是否为回环地址(如127.0.0.1、localhost、[::1]):
修改Filter代码:
import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Set; public class InternalFilter implements Filter { private static final Set<String> INTERNAL_IPS = Set.of("127.0.0.1", "0:0:0:0:0:0:0:1", "localhost"); @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { String remoteAddr = request.getRemoteAddr(); String remoteHost = request.getRemoteHost(); if (INTERNAL_IPS.contains(remoteAddr) || INTERNAL_IPS.contains(remoteHost)) { chain.doFilter(request, response); return; } HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.sendError(HttpServletResponse.SC_FORBIDDEN, "Internal API only"); } }
缺点:如果服务器允许外部访问回环地址(比如容器端口映射到外部),这个方法会有安全风险,仅建议在严格隔离的环境中使用。
内容的提问来源于stack exchange,提问作者Oliver
相关产品推荐
相关产品推荐

