【问题标题】:Which environment variable to use on Heroku for services that only listen to https在 Heroku 上为只监听 https 的服务使用哪个环境变量
【发布时间】:2026-02-07 14:05:02
【问题描述】:

我正在使用将部署在 Heroku 上的 AspNet 核心设置一个仅限 https 的 Web API 服务。部署是通过 docker 完成的,所以我配置了一个 Dockerfile。但是每当我部署到 Heroku 时,我都会收到与 https 端口绑定相关的错误。我想知道 Heroku 是否为 https 提供了一个特殊的环境变量,服务可以在其中绑定以指定服务应该监听的 https 端口。

AspNet 核心提供 2 个环境变量 ASPNETCORE_HTTPS_PORT=5001ASPNETCORE_URLS=https://*:5001 可以指定服务应该监听的 https 端口。

但是由于 Heroku 不允许 Web 进程手动指定它应该监听的端口,它们提供了一个 PORT 环境变量,Web 应用可以绑定到。

我尝试使用ASPNETCORE_HTTPS_PORT=$PORTASPNETCORE_URLS=https://*:$PORT,但出现以下错误:

crit: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.Net.Sockets.SocketException (13): Permission denied at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName) 
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass21_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()

【问题讨论】:

  • “我想知道 Heroku 是否为 https 提供了一个特殊的环境变量,服务可以在其中绑定以指定服务应该监听的 https 端口。”——它没有。我不知道那些特定的 .NET Core 变量,但就 Heroku 而言,只有 PORT。这应该工作。能否分享一下你Dockerfile的相关部分?
  • 我怀疑你的环境变量是否传递正确。因为它适用于我的 ASP.NET Core。只有当我以错误的方式指定/传递这些设置时才会发生这种情况。
  • 现在想想,Heroku 通常不希望您的应用程序内置 HTTPS。那是可以添加的东西,例如通过 ACM 或自定义证书。您是否真的在 Docker 容器中运行带有任意证书的 HTTPS 服务器?
  • @Chris 感谢您的澄清。我现在能够解决这个问题。我正在使用 ACM,但我的应用程序之前尝试在将 http 请求重定向到 https 时监听 http 和 https 端口;然后当我发现 heroku 只支持 PORT var 时,我单独切换到 https。但是现在我知道heroku uses a load balancer 通过 http 代理 https 请求,我能够以正确的方式配置我的应用程序。我将很快发布我的解决方案。

标签: c# asp.net-core heroku


【解决方案1】:

因此,在浏览了 Heroku 的文档(广泛地)之后,我能够解决这个问题。以下是与此问题相关的主要发现:

  1. Heroku uses a load balancer 代理其所有请求。
  2. Heroku 会终止来自您应用的所有 SSL 通信,因此所有请求都通过 http 转发到您的应用;您客户的 https 请求通过 http 进行代理。
  3. 由于请求被代理,Heroku passes Forwarded headers 用于原始请求。
  4. 您的应用只能接收请求和should only listen to the PORT 环境变量。

现在我有了这个想法,我能够正确配置我的应用程序。

在 http 而不是 https 上收听:ASPNETCORE_URLS=http://*:$PORT

在 AspNet 核心中间件管道中使用 FowardedHeaders 和 Rewriter 中间件:

var forwardedHeadersOptions = new ForwardedHeadersOptions {
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);

var rewriteOptions = new RewriteOptions ().AddRedirectToHttps(308);
app.UseRewriter(rewriteOptions);
...

ForwardedHHeaders 中间件maps the Forwarded headers to HttpContext.Request。还有重写器中间件will redirect http request scheme to https

【讨论】:

    最近更新 更多