Vert.x将http重定向到https

Alb*_*ola 5 java vert.x java-11 vertx4

我们用Vert.x 4重新编写了我们的Web服务,我们感到非常满意。在将它们投入生产之前,我们要保护它们安全,并尝试启用https。这是主要版本:

public class MainVerticle extends AbstractVerticle {

  @Override
  public void start() throws Exception {
    //Deploy the HTTP server
    vertx.deployVerticle(
      "com.albertomiola.equations.http.HttpServerVerticle",
      new DeploymentOptions().setInstances(3)
    );
  }

  // I use this only in IntelliJ Idea because when I hit "Run" the build starts
  public static void main(String[] args) {
    Launcher.executeCommand("run", MainVerticle.class.getName());
  }

}
Run Code Online (Sandbox Code Playgroud)

这是HTTP服务器Verticle代码中最相关的部分:

public class HttpServerVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    var options = new HttpServerOptions();
    options.setPort(443)
           .setSSl(true)
           .setPemTrustOptions(...)
           .setPemKeyCertOptions(...);

    var server = vertx.createHttpServer(options);
    var router = Router.router(vertx);

    //Start
    server
      .requestHandler(router)
      .listen(portNumber, ar -> {
        if (ar.succeeded()) {
          startPromise.complete();
        } else {
          startPromise.fail(ar.cause());
        }
      });
  }

}
Run Code Online (Sandbox Code Playgroud)

上面的代码可以正常工作,因为我的网站可以通过https://website.ithttps://www.website.it访问 (带有letencrypt证书)。


问题是,当我尝试访问http://website.ithttp://www.website.it时,它不起作用(这意味着我无法看到房屋,因为服务器无法访问)。

如何将http://website.it重定向到https // website.it?

我已经在Google上搜索了很多,但设法找到的是:

  • 这个与我一样设置HTTPS的vertx示例,但未提及重定向
  • 这样的问题似乎告诉我该怎么办,但我不知道该怎么办,而且我不确定该设置是否必须在HttpServerOption对象中进行

也许我的https配置错误?我在IntelliJ IDEA(Maven构建)和Vert.x 4最新版本上使用Java 11。谢谢

Alb*_*ola 5

我提出的最终解决方案如下所示,它们是等效的。这两种情况的想法都是有一个 http 服务器(当然监听端口 80)将每个调用重定向到 https 服务器。

因此,就我而言,我可以完全按照我的意愿行事,因为http://mydomain.it按预期重定向到https://mydomain.it。例如,当我打电话给

http://mydomain.it/api/polynomial/laguerre
Run Code Online (Sandbox Code Playgroud)

有一个活着的 http 服务器接收到请求,但随后它立即将球扔给

https://mydomain.it/api/polynomial/laguerre
Run Code Online (Sandbox Code Playgroud)

当然,如果您直接调用 https 版本,则不会发生此“中间”步骤。


使用 Vert.x

上一篇文章中 Hugo 的答案给出了使用 Vertx 的有效解决方案。我有一个主垂直体,如下所示:

public class MainVerticle extends AbstractVerticle {

  @Override
  public void start() throws Exception {

    //Deploy the HTTPS server
    vertx.deployVerticle(
      "com.albertomiola.equations.http.HttpsServerVerticle",
      new DeploymentOptions().setInstances(n)
    );

    //Deploy the HTTP server
    vertx.deployVerticle(
      "com.albertomiola.equations.http.HttpServerVerticle",
      new DeploymentOptions().setInstances(1)
    );
  }

}
Run Code Online (Sandbox Code Playgroud)

第一个 verticle 是“真正的”网站,因为它包含我的网络服务中所需的所有逻辑(路由器、处理程序、模型...),它看起来像这样:

public class HttpsServerVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    // Setup the HTTPS
    var httpOptions = new HttpServerOptions()
      .setCompressionSupported(true)
      .setPort(443)
      .setSsl(true)
      .setPemTrustOptions(...)
      .setPemKeyCertOptions(...);

    // Start the server and the routes
    var server = vertx.createHttpServer(httpOptions);
    var router = Router.router(vertx);

    //Start
    server
      .requestHandler(router)
      .listen(ar -> {
        if (ar.succeeded()) {
          startPromise.complete();
        } else {
          startPromise.fail(ar.cause());
        }
      });
  }

}
Run Code Online (Sandbox Code Playgroud)

相反,另一个 verticle 只是一个 http 服务器,它永久重定向(使用 301)到 https 版本的 Web 服务器。这是代码:

public class HttpsServerVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    var server = vertx.createHttpServer(httpOptions);
    var router = Router.router(vertx);

    //Start
    server
      .requestHandler(r -> {
          r.response()
           .setStatusCode(301)
           .putHeader("Location", r.absoluteURI().replace("http", "https"))
           .end();
      });
  }

}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,有 2 个服务器处于活动状态,但实际上就像只有 1 个服务器一样,因为 http 服务器(端口 80)将每个调用重定向到 https 服务器(端口 443)。


使用 Nginx

我测试过的另一种方法需要 nginx,但它执行的操作与我在上面的示例中执行的操作相同。它侦听端口 80 上的 http 请求,然后将它们重定向到 https 版本。

  1. 在我的 Ubuntu 服务器(或任何你拥有的服务器)上安装 Nginx
  2. 进入/etc/nginx/nginx.conf我的例子中的配置文件
  3. 添加以下代码

    http {
        server {
                listen         80;
                server_name    mydomain.it;
                return         301 https://$server_name$request_uri;
        }
    
        //other code...
    }
    
    Run Code Online (Sandbox Code Playgroud)
    1. 重新启动systemctl restart nginx

现在,每次对 http 版本的调用都会重定向到 https 版本。感谢用户injecteer向我建议了这种方式。

我使用这种方法是因为我不喜欢只为 http 版本使用单个 verticle。Vertx 网站上的这篇文章也表明这种方法是有效的:

在生产中通过前端 HTTP 服务器/代理(如 Nginx)公开 HTTP 服务器是很常见的,并让它使用 HTTPS 进行传入连接。Vert.x还可以自行暴露HTTPS,从而提供端到端加密。

所以,是的,使用 Vertx 设置 https(我建议 letencrypt 认证),但也使用 nginx 将调用重定向到 https。


我错误地认为我可以用 Vertx 做一些特殊的事情来处理这个重定向,但这是不可能的。在这个答案中的人们的建议以及一些很好的谷歌搜索之后,我了解到这种方法很常见,这就是我应该做的!