2015-03-30 3 views
3

Я пытаюсь отключить метод HTTP TRACE во встроенном Jetty. В Jetty doc информация о том, что трассировка HTTP отключена по умолчанию, но для встроенного она по-прежнему включена. Я пытался отключить трассировку как ограничение безопасности, как это сделано в jetty.xml.Java embedded jetty принимает метод HTTP TRACE

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 

ответ

1

На вашем Constraint объекта, вам нужно вызвать setAuthenticate(true), и убедитесь, что вы не вызываете setRoles(String[]). Это делает его эквивалентом <security-constraint> с пустым <auth-constraint>, который запрещает доступ.

Причина, по которой она работает с DefaultServlet, а не CXFServlet, заключается в том, что DefaultServlet специально отказывает в доступе к методу TRACE.

+0

Это добавление работает правильно. Благодарю. –

-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 
*~ 

TRACE Запрос:

$ 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 
+0

Спасибо, для вас ответ. Кажется, проблема не в Jetty, а в CXFServlet. Когда я отключу CXF и поставлю сервлет в ваш пример ответа Jetty с ошибкой 405. –

+0

Кажется, что этот пример работает только потому, что использует DefaultServlet, который явно запрещает TRACE, в отличие от OP, который использует CXFServlet. Это все равно будет проблемой для любого другого сервлета, не распространяющего DefaultServlet. Ограничение безопасности в этом примере по существу является NOOP. Ограничение безопасности, если оно принудительно привело бы к ошибке 403 Forbidden, вместо ошибки 405 Method Not Allowed, генерируемой DefaultServlet. – Christopher

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); 
     } 
    } 
} 
2

Ответ Ян работает (конечно). Однако это приведет к тому, что причал выведет предупреждение при запуске.

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

Чтобы избежать этого сначала добавить ограничение, как в ответ Яну (отключить 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); 
    } 
} 

Я понял это решение после того, как я нашел this issue в компании Google AppEngine-Java-VM-среды выполнения и the fix, как на январь Код выше должен делать то же самое, XML config там.

+0

Это действительно работает, однако оно выбрасывает 403 (Запрещено), а не более подходящее 405 (Method Not Allowed) –

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); 
    } 
.... 
+0

. Это то, что я сделал бы, поскольку он не привязан к Jetty или чему-то еще. Кроме того, тривиально. – eis

Смежные вопросы