在 Heroku 上使用 ring 侦听 HTTPS 端口时出现权限被拒绝错误

Permission denied errors when listening on HTTPS ports with ring on Heroku

根据 this question 中接受的答案,我使用命令 keytool -keystore keystore.jks -genkey -alias server 生成了一个密钥库,并将其提交到我项目的 resources 文件夹中的源代码管理。然后,我将服务器设置为使用该密钥库。

src/clj/foo/server.clj

(ns foo.server
  (:require [foo.handler :refer [app]]
            [config.core :refer [env]]
            [ring.adapter.jetty :refer [run-jetty]])
  (:gen-class))

 (defn -main [& args]
   (let [port (Integer/parseInt (or (env :port) "3000"))]
     (run-jetty app {:port 8443
                     :join? false
                     :ssl? true
                     :keystore "./resources/keystore.jks"
                     :key-password "foo"})))

但是,如以下日志所示,此配置不起作用。但是为什么?

日志

$ heroku logs --app foo-test
2017-02-02T23:11:42.161056+00:00 heroku[web.1]: Process exited with status 1
2017-02-02T23:11:42.295501+00:00 heroku[web.1]: State changed from starting to crashed
2017-02-02T23:11:43.413805+00:00 app[web.1]: 2017-02-02 23:11:43.412:INFO::main: Logging initialized @10893ms
2017-02-02T23:11:43.520845+00:00 app[web.1]: 2017-02-02 23:11:43.518:INFO:oejs.Server:main: jetty-9.2.z-SNAPSHOT
2017-02-02T23:11:43.987674+00:00 app[web.1]: 2017-02-02 23:11:43.986:INFO:oejs.ServerConnector:main: Started ServerConnector@29a6b0b2{HTTP/1.1}{0.0.0.0:8443}
2017-02-02T23:11:43.989942+00:00 app[web.1]: 2017-02-02 23:11:43.988:WARN:oejuc.AbstractLifeCycle:main: FAILED ServerConnector@31da0434{SSL-http/1.1}{0.0.0.0:443}: java.net.SocketException: Permission denied
2017-02-02T23:11:43.989944+00:00 app[web.1]: java.net.SocketException: Permission denied
2017-02-02T23:11:43.989945+00:00 app[web.1]:    at sun.nio.ch.Net.bind0(Native Method)
2017-02-02T23:11:43.989945+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:433)
2017-02-02T23:11:43.989946+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:425)
2017-02-02T23:11:43.989948+00:00 app[web.1]:    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
2017-02-02T23:11:43.989947+00:00 app[web.1]:    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
2017-02-02T23:11:43.989948+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
2017-02-02T23:11:43.989949+00:00 app[web.1]:    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
2017-02-02T23:11:43.989950+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
2017-02-02T23:11:43.989951+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:43.989952+00:00 app[web.1]:    at org.eclipse.jetty.server.Server.doStart(Server.java:366)
2017-02-02T23:11:43.989953+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:43.989953+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invokeStatic(jetty.clj:137)
2017-02-02T23:11:43.989954+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:100)
2017-02-02T23:11:43.989954+00:00 app[web.1]:    at foo.server$_main.invokeStatic(server.clj:9)
2017-02-02T23:11:43.989955+00:00 app[web.1]:    at foo.server$_main.doInvoke(server.clj:7)
2017-02-02T23:11:43.989956+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:397)
2017-02-02T23:11:43.989956+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:375)
2017-02-02T23:11:43.989957+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:152)
2017-02-02T23:11:43.989958+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:43.989959+00:00 app[web.1]:    at clojure.main$main_opt.invokeStatic(main.clj:314)
2017-02-02T23:11:43.989958+00:00 app[web.1]:    at clojure.core$apply.invokeStatic(core.clj:646)
2017-02-02T23:11:43.989959+00:00 app[web.1]:    at clojure.main$main_opt.invoke(main.clj:310)
2017-02-02T23:11:43.989961+00:00 app[web.1]:    at clojure.main$main.invokeStatic(main.clj:421)
2017-02-02T23:11:43.989961+00:00 app[web.1]:    at clojure.main$main.doInvoke(main.clj:384)
2017-02-02T23:11:43.989962+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:421)
2017-02-02T23:11:43.989963+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:156)
2017-02-02T23:11:43.989963+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:383)
2017-02-02T23:11:43.989964+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:43.989967+00:00 app[web.1]:    at clojure.main.main(main.java:37)
2017-02-02T23:11:43.991194+00:00 app[web.1]: 2017-02-02 23:11:43.990:WARN:oejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.Server@6e24ce51: java.net.SocketException: Permission denied
2017-02-02T23:11:43.991195+00:00 app[web.1]: java.net.SocketException: Permission denied
2017-02-02T23:11:43.991196+00:00 app[web.1]:    at sun.nio.ch.Net.bind0(Native Method)
2017-02-02T23:11:43.991197+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:433)
2017-02-02T23:11:43.991197+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:425)
2017-02-02T23:11:43.991198+00:00 app[web.1]:    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
2017-02-02T23:11:43.991199+00:00 app[web.1]:    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
2017-02-02T23:11:43.991200+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
2017-02-02T23:11:43.991200+00:00 app[web.1]:    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
2017-02-02T23:11:43.991201+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
2017-02-02T23:11:43.991202+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:43.991203+00:00 app[web.1]:    at org.eclipse.jetty.server.Server.doStart(Server.java:366)
2017-02-02T23:11:43.991203+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:43.991204+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invokeStatic(jetty.clj:137)
2017-02-02T23:11:43.991205+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:100)
2017-02-02T23:11:43.991205+00:00 app[web.1]:    at foo.server$_main.invokeStatic(server.clj:9)
2017-02-02T23:11:43.991207+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:397)
2017-02-02T23:11:43.991206+00:00 app[web.1]:    at foo.server$_main.doInvoke(server.clj:7)
2017-02-02T23:11:43.991207+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:375)
2017-02-02T23:11:43.991208+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:152)
2017-02-02T23:11:43.991209+00:00 app[web.1]:    at clojure.core$apply.invokeStatic(core.clj:646)
2017-02-02T23:11:43.991209+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:43.991210+00:00 app[web.1]:    at clojure.main$main_opt.invokeStatic(main.clj:314)
2017-02-02T23:11:43.991211+00:00 app[web.1]:    at clojure.main$main_opt.invoke(main.clj:310)
2017-02-02T23:11:43.991211+00:00 app[web.1]:    at clojure.main$main.invokeStatic(main.clj:421)
2017-02-02T23:11:43.991212+00:00 app[web.1]:    at clojure.main$main.doInvoke(main.clj:384)
2017-02-02T23:11:43.991213+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:383)
2017-02-02T23:11:43.991213+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:156)
2017-02-02T23:11:43.991212+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:421)
2017-02-02T23:11:43.991214+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:43.991218+00:00 app[web.1]:    at clojure.main.main(main.java:37)
2017-02-02T23:11:44.073981+00:00 app[web.1]: 2017-02-02 23:11:44.073:INFO:oejs.ServerConnector:main: Stopped ServerConnector@29a6b0b2{HTTP/1.1}{0.0.0.0:8443}
2017-02-02T23:11:44.095345+00:00 app[web.1]: Exception in thread "main" java.net.SocketException: Permission denied
2017-02-02T23:11:44.074293+00:00 app[web.1]: 2017-02-02 23:11:44.074:INFO:oejs.ServerConnector:main: Stopped ServerConnector@31da0434{SSL-http/1.1}{0.0.0.0:443}
2017-02-02T23:11:44.095700+00:00 app[web.1]:    at sun.nio.ch.Net.bind0(Native Method)
2017-02-02T23:11:44.095798+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:433)
2017-02-02T23:11:44.095861+00:00 app[web.1]:    at sun.nio.ch.Net.bind(Net.java:425)
2017-02-02T23:11:44.095958+00:00 app[web.1]:    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
2017-02-02T23:11:44.096022+00:00 app[web.1]:    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
2017-02-02T23:11:44.096113+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
2017-02-02T23:11:44.096268+00:00 app[web.1]:    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
2017-02-02T23:11:44.096179+00:00 app[web.1]:    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
2017-02-02T23:11:44.096338+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:44.096430+00:00 app[web.1]:    at org.eclipse.jetty.server.Server.doStart(Server.java:366)
2017-02-02T23:11:44.096495+00:00 app[web.1]:    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
2017-02-02T23:11:44.096585+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invokeStatic(jetty.clj:137)
2017-02-02T23:11:44.096727+00:00 app[web.1]:    at foo.server$_main.invokeStatic(server.clj:9)
2017-02-02T23:11:44.096649+00:00 app[web.1]:    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:100)
2017-02-02T23:11:44.096808+00:00 app[web.1]:    at foo.server$_main.doInvoke(server.clj:7)
2017-02-02T23:11:44.096872+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:397)
2017-02-02T23:11:44.096962+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:375)
2017-02-02T23:11:44.097025+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:152)
2017-02-02T23:11:44.097112+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:44.097671+00:00 app[web.1]:    at clojure.core$apply.invokeStatic(core.clj:646)
2017-02-02T23:11:44.097769+00:00 app[web.1]:    at clojure.main$main_opt.invokeStatic(main.clj:314)
2017-02-02T23:11:44.097834+00:00 app[web.1]:    at clojure.main$main_opt.invoke(main.clj:310)
2017-02-02T23:11:44.097908+00:00 app[web.1]:    at clojure.main$main.invokeStatic(main.clj:421)
2017-02-02T23:11:44.097989+00:00 app[web.1]:    at clojure.main$main.doInvoke(main.clj:384)
2017-02-02T23:11:44.098056+00:00 app[web.1]:    at clojure.lang.RestFn.invoke(RestFn.java:421)
2017-02-02T23:11:44.098147+00:00 app[web.1]:    at clojure.lang.Var.invoke(Var.java:383)
2017-02-02T23:11:44.098312+00:00 app[web.1]:    at clojure.lang.Var.applyTo(Var.java:700)
2017-02-02T23:11:44.098210+00:00 app[web.1]:    at clojure.lang.AFn.applyToHelper(AFn.java:156)
2017-02-02T23:11:44.098419+00:00 app[web.1]:    at clojure.main.main(main.java:37)
2017-02-02T23:11:44.314609+00:00 heroku[web.1]: Process exited with status 1
2017-02-02T23:12:07.539455+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=foo-test.herokuapp.com request_id=dff25101-ab3c-4464-ac06-d0e5a9586797 fwd="107.3.128.7" dyno= connect= service= status=503 bytes=

您的 -main 相当可疑地忽略了它的端口环境变量。你解析它,然后忽略它并使用 8443 不管怎样。

:port 用于 http
:ssl-port 适用于 https

https://ring-clojure.github.io/ring/ring.adapter.jetty.html

您的权限被拒绝,因为它试图绑定到默认的 SSL 端口 443,您需要 sudo 访问更少的端口比 1024

2017-02-02T23:11:43.987674+00:00 app[web.1]: 2017-02-02 23:11:43.986:INFO:oejs.ServerConnector:main: Started ServerConnector@29a6b0b2{HTTP/1.1}{0.0.0.0:8443}
2017-02-02T23:11:43.989942+00:00 app[web.1]: 2017-02-02 23:11:43.988:WARN:oejuc.AbstractLifeCycle:main: FAILED ServerConnector@31da0434{SSL-http/1.1}{0.0.0.0:443}: java.net.SocketException: Permission denied

注意 {HTTP/1.1}{0.0.0.0:8443} 根据您的配置成功绑定
{SSL-http/1.1}{0.0.0.0:443} 失败