java - Vert.x 将 http 重定向到 https

标签 java vert.x java-11 vertx4

我们已经用 Vert.x 4 重写了我们的网络服务,我们非常满意。在将它们投入生产之前,我们希望保护它们并且我们正在尝试启用 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());
  }

}

这是 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());
        }
      });
  }

}

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


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

How can I redirect http://website.it to https//website.it?

我用谷歌搜索了很多,我设法找到的是:

  • > this像我一样设置 HTTPS 的 vertx 示例,但它没有提到重定向
  • > this SO 问题似乎告诉我该怎么做,但我不明白该怎么做,我不确定该设置是否必须进入 HttpServerOption 对象

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

最佳答案

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

所以在我的例子中,我可以做我想做的事,因为 http://mydomain.it被重定向到 https://mydomain.it正如预期的那样。例如当我调用

http://mydomain.it/api/polynomial/laguerre

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

https://mydomain.it/api/polynomial/laguerre

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


使用 Vert.x

Hugo 在 above post 中的回答使用 Vertx 给出一个有效的解决方案。我有一个看起来像这样的主 Verticle:

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

}

第一个 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());
        }
      });
  }

}

另一个 Verticle 只是一个 永久 重定向(使用 301)到 https 版本的网络服务器的 http 服务器。这是代码:

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

}

以这种方式有 2 个服务器处于 Activity 状态,但实际上它就像只有 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...
    }
    
    1. 使用 systemctl restart nginx 重启

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

我之所以使用这种方法,是因为我不喜欢只为 http 版本设置一个 Verticle。还有 this Vertx 网站上的文章说这种方法是有效的:

It is common to expose HTTP servers in production through a front HTTP server / proxy like Nginx, and have it use HTTPS for incoming connections. Vert.x can also expose HTTPS by itself, so as to provide end-to-end encryption.

是的,使用 Vertx 设置 https(我建议使用 letsencrypt 认证),同时使用 nginx 将调用重定向到 https。


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

关于java - Vert.x 将 http 重定向到 https,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57962272/

相关文章:

Java - 线程中出现异常 "main"java.util.ConcurrentModificationException

java - Vertx Event 总线桥接 'io.vertx~mod-web-server~2.0.0' ,未获取数据

ssl-certificate - javax.net.ssl.SSLHandshakeException : Received fatal alert: handshake_failure for google-client-api

Java11 嵌套类,同时对代码使用 Fluent Design Structure

java - JDK11中Oracle的源码和openJDK的源码区别在哪里

java - 在 Mongo 中插入 JSON

java - 如何获取经过身份验证的网络点击总数?

java - Vertx3 - EventBus 在集群中不工作

java - executeBlocking期间Vertx阻塞线程异常

java - 将图像插入边框作为背景