可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to disable HTTP TRACE method in embedded Jetty. In Jetty doc's is info that HTTP trace is disabled by default, but for embedded it is still enabled. I was trying to disable trace as a security constraint as is done in 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);
Example output from 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:
On your Constraint
object, you need to call setAuthenticate(true)
, and ensure that you don't call setRoles(String[])
. This makes it the equivalent of a <security-constraint>
with an empty <auth-constraint>
, which forbids access.
The reason it works with the DefaultServlet
and not the CXFServlet
is because the DefaultServlet
specifically denies access to the TRACE method.
回答2:
Extending the Server class and overriding the handle() method worked best for me.
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);
}
}
}
回答3:
You can create a filter:
...
@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);
}
....
回答4:
Jan's answer works (of course). However, it will cause jetty to print a warning on startup.
WARNING ... SecurityHandler ... has uncovered http methods for path ...
To avoid this first add the constraint as in Jan's answer (disable TRACE) and then add another constraint (allow everything but TRACE). I invoke the following code for each 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);
}
}
I figured out this solution after I found this issue in Google's appengine-java-vm-runtime and the fix, both by Jan. The code above should do the same as the XML config there.
回答5:
Your code works as-is.
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);
}
}
}
The test.
Normal GET request:
$ curl http://127.0.0.1:9090/.gitignore
.classpath
.project
.settings
target/
*.swp
*.log
*~
TRACE Request:
$ 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