Java embedded jetty正在接受HTTP TRACE方法

时间:2015-03-30 14:06:09

标签: spring http jetty trace embedded-jetty

我正在尝试在嵌入式Jetty中禁用HTTP TRACE方法。在Jetty doc中,默认情况下禁用HTTP跟踪,但对于嵌入式,它仍然是启用的。我试图将trace作为安全约束禁用,就像在jetty.xml中一样。

    ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
    servletHandler.setClassLoader(Server.class.getClassLoader());
    servletHandler.setContextPath("/");
    servletHandler.addEventListener(new ContextLoaderListener());
    servletHandler.addServlet(new ServletHolder(new CXFServlet()), "/*");
    servletHandler.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
    servletHandler.setInitParameter("contextConfigLocation", BeansConfig.class.getName());
    servletHandler.setInitParameter("javax.ws.rs.Application", DispatcherConfig.class.getName());

     /*
     * <security-constraint>
     * <web-resource-collection>
     * <web-resource-name>Disable TRACE</web-resource-name>
     * <url-pattern>/</url-pattern>
     * <http-method>TRACE</http-method>
     * </web-resource-collection>
     * <auth-constraint/>
     * </security-constraint>
     */
     Constraint constraint = new Constraint();
     constraint.setName("Disable TRACE");

     ConstraintMapping mapping = new ConstraintMapping();
     mapping.setConstraint(constraint);
     mapping.setMethod("TRACE");
     mapping.setPathSpec("/"); // this did not work same this mapping.setPathSpec("/*");

     ConstraintSecurityHandler securityHandler = (ConstraintSecurityHandler) servletHandler.getSecurityHandler();
     securityHandler.addConstraintMapping(mapping);

soapUI的输出示例:

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 143
Server: Jetty(9.0.6.v20130930)

TRACE / HTTP/1.1
Connection: keep-alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Host: 192.168.33.115
Accept-Encoding: gzip,deflate

5 个答案:

答案 0 :(得分:4)

扩展Server类并覆盖handle()方法最适合我。

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;

public class MyServer extends Server {

    @Override
    public void handle(HttpChannel<?> connection) throws IOException, ServletException {
        Request request=connection.getRequest();
        Response response=connection.getResponse();

        if ("TRACE".equals(request.getMethod())){
            request.setHandled(true);
            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        } else {
            super.handle(connection);
        }
    }
}

答案 1 :(得分:2)

Jan的回答是有效的(当然)。但是,它会导致jetty在启动时打印警告。

WARNING ... SecurityHandler ... has uncovered http methods for path ...

为了避免这种情况,首先在Jan的答案中添加约束(禁用TRACE),然后添加另一个约束(允许除TRACE之外的所有约束)。我为每个ServletContextHandler调用以下代码:

private void disableTraceMethodForHandler(final ServletContextHandler servletContextHandler) {
    SecurityHandler securityHandler = servletContextHandler.getSecurityHandler();
    if (securityHandler == null) {
        securityHandler = new ConstraintSecurityHandler();
        servletContextHandler.setSecurityHandler(securityHandler);
    }
    if (securityHandler instanceof ConstraintSecurityHandler) {
        ConstraintSecurityHandler constraintSecurityHandler = (ConstraintSecurityHandler) securityHandler;

        ConstraintMapping disableTraceMapping = new ConstraintMapping();
        Constraint disableTraceConstraint = new Constraint();
        disableTraceConstraint.setName("Disable TRACE");
        disableTraceConstraint.setAuthenticate(true);
        disableTraceMapping.setConstraint(disableTraceConstraint);
        disableTraceMapping.setPathSpec("/");
        disableTraceMapping.setMethod("TRACE");
        constraintSecurityHandler.addConstraintMapping(disableTraceMapping);

        ConstraintMapping enableEverythingButTraceMapping = new ConstraintMapping();
        Constraint enableEverythingButTraceConstraint = new Constraint();
        enableEverythingButTraceConstraint.setName("Enable everything but TRACE");
        enableEverythingButTraceMapping.setConstraint(enableEverythingButTraceConstraint);
        enableEverythingButTraceMapping.setMethodOmissions(new String[] {"TRACE"});
        enableEverythingButTraceMapping.setPathSpec("/");
        constraintSecurityHandler.addConstraintMapping(enableEverythingButTraceMapping);
    }
}

我在1月份在Google的appengine-java-vm-runtime和this issue中找到the fix之后找到了这个解决方案。上面的代码应该和XML一样配置那里。

答案 2 :(得分:2)

您可以创建过滤器:

...
@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        if ("TRACE".equalsIgnoreCase(httpRequest.getMethod())) {
            httpResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }
        chain.doFilter(request, response);
    }
....

答案 3 :(得分:1)

Constraint对象上,您需要致电setAuthenticate(true),并确保不致电setRoles(String[])。这使其等同于<security-constraint>,其中<auth-constraint>为空,禁止访问。

它与DefaultServlet而不是CXFServlet一起使用的原因是因为DefaultServlet明确拒绝访问TRACE方法。

答案 4 :(得分:-1)

您的代码按原样运行。

package jetty;

import java.io.File;
import java.nio.file.Path;

import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;

public class BanTraceExample
{
    private static final Logger LOG = Log.getLogger(BanTraceExample.class);

    public static void main(String[] args)
    {
        Server server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(9090);
        server.addConnector(connector);

        Path basePath = new File(System.getProperty("test.base",System.getProperty("user.dir"))).toPath().toAbsolutePath();
        LOG.info("Base Directory: {}",basePath);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
        context.setContextPath("/");
        server.setHandler(context);

        Constraint constraint = new Constraint();
        constraint.setName("Disable TRACE");

        ConstraintMapping mapping = new ConstraintMapping();
        mapping.setConstraint(constraint);
        mapping.setMethod("TRACE");
        mapping.setPathSpec("/");

        ConstraintSecurityHandler securityHandler = (ConstraintSecurityHandler)context.getSecurityHandler();
        securityHandler.addConstraintMapping(mapping);

        ServletHolder holderDef = new ServletHolder("test",DefaultServlet.class);
        holderDef.setInitParameter("resourceBase",basePath.toString());
        holderDef.setInitParameter("dirAllowed","true");
        context.addServlet(holderDef,"/");

        try
        {
            server.start();
            server.join();
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }
}

测试。

正常的GET请求:

$ curl http://127.0.0.1:9090/.gitignore
.classpath
.project
.settings
target/
*.swp
*.log
*~

跟踪请求:

$ curl -v -X TRACE http://127.0.0.1:9090/.gitignore
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 9090 (#0)
> TRACE /.gitignore HTTP/1.1
> User-Agent: curl/7.40.0
> Host: 127.0.0.1:9090
> Accept: */*
>
< HTTP/1.1 405 Method Not Allowed
< Date: Mon, 30 Mar 2015 21:48:53 GMT
< Cache-Control: must-revalidate,no-cache,no-store
< Content-Type: text/html; charset=ISO-8859-1
< Content-Length: 297
< Server: Jetty(9.2.10.v20150310)
<
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
<title>Error 405 </title>
</head>
<body>
<h2>HTTP ERROR: 405</h2>
<p>Problem accessing /.gitignore. Reason:
<pre>    Method Not Allowed</pre></p>
<hr /><i><small>Powered by Jetty://</small></i>
</body>
</html>
* Connection #0 to host 127.0.0.1 left intact