使用 Jetty 将 HTTP 重定向到同一端口上的 HTTPS ---从请求中识别 http 与 https

问题描述

从 Jetty 9.4 开始。?可以在同一端口上运行 HTTP 和 HTTPs。 The gist of it is

httpconnectionFactory http = new httpconnectionFactory();
SslConnectionFactory https = new SslConnectionFactory(sslCtxFactory,http.getProtocol());
DetectorConnectionFactory conFactory = new DetectorConnectionFactory(https);
ServerConnector connector = new ServerConnector(server,conFactory,http);

由于我只想提供 HTTPS,因此我想将每个 http://host:port/stuff 重定向https://host:port/stuff。我知道如何使用 RedirectRule 的子类或仅使用名为 early 的处理程序进行重定向

我遇到的问题是:我如何从请求中确定连接是 HTTP 而不是 HTTPS?

当我在调试器中查看 Request 时,没有发现任何提示,一切看起来都好像是 http 即使连接是 httpsRequest.isSecure() 都是假的,方案是 http 等等。我能想到的最好的事情是:

if (Request.getHttpChannel().getEndPoint() instanceof SslConnection.DecryptedEndPoint())

这是一个带注释和剪辑的堆栈跟踪,显示了我的处理程序如何相互包装:

at server.HttpToHttpsRedirectRule.matchAndApply(HttpToHttpsRedirectRule.java:34)
         "^^ Here I do the matchAndApply myself and then use a jetty RedirectRule.apply"
         "The redirect works OK,but figuring whether it is HTTPS does not work"
at org.eclipse.jetty.rewrite.handler.RuleContainer.apply(RuleContainer.java:166)
at org.eclipse.jetty.rewrite.handler.RuleContainer.matchAndApply(RuleContainer.java:145)
at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:317)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:766)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at server.LogHandler.handle(LogHandler.java:33)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
                                   "^^^ the outermost handler"
[clip]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:380)
                           "^^^ we decoded the ssl and Feed the lower levels plain HTTP"
[clip]
at org.eclipse.jetty.io.ssl.SslConnection$1.run(SslConnection.java:146)
                           "^^^ we are in SSL"

在我的 HttpToHttpsRedirectRule 中,我想弄清楚它是哪个连接。有没有比上面提到的 instanceof 更明智的解决方案?

解决方法

为了确保保留原始方案(可能还有更多)信息,有必要在 http 配置中添加一个 SecureRequestCustomizer,如下所示:

HttpConfiguration httpConf = new HttpConfiguration();
httpConf.addCustomizer(new SecureRequestCustomizer());
HttpConnectionFactory http = new HttpConnectionFactory(httpConf);
SslConnectionFactory https = new SslConnectionFactory(sslCtxFactory,http.getProtocol());
DetectorConnectionFactory conFactory = new DetectorConnectionFactory(https);
ServerConnector connector = new ServerConnector(server,conFactory,http);

找到关键提示in the jetty mailing list