Clojure:heroku 上的 wrap-ssl-redirect?
Clojure: wrap-ssl-redirect on heroku?
我刚刚尝试添加此包装器 (-> routes (wrap-ssl-redirect))
以自动将 http 重定向到 https,但是当我部署到 heroku 时,https://
在我的浏览器和网站中没有变绿未加载。
不是默认的 heroku 端口 443
,它也应该是 wrap-ssl-redirect
函数的默认端口吗?
怎么了?
谢谢!
编辑:
我的代码:
(defn prod-app [routes]
(-> routes
(wrap-keyword-params)
(wrap-params)
(wrap-ssl-redirect)))
(defn -main []
(let [port (Integer/parseInt (get (System/getenv) "PORT" "5000"))]
(jetty/run-jetty (prod-app domain-specific-routes)
{:port port :join? false})))
编辑 2:
我刚找到可以解决我的问题的帖子:
想出了这个 require-https
处理程序 fn:
(defn https-url [request-url]
(str "https://"
(:server-name request-url)
":"
(:server-port request-url)
(:uri request-url)))
(defn require-https
[handler]
(fn [request]
(if (and (= (:scheme request) :http)
(= (get-in request [:headers "host"]) "secure.mydomain.com"))
(ring.util.response/redirect (https-url request))
(handler request))))
但是当我尝试连接到 http://secure.mydomain.com
时,我在浏览器地址栏中看到一个端口 https://secure.mydomain.com:80/
并收到此消息 ERR_SSL_PROTOCOL_ERROR
。
在 Heroku 上,你需要 bind to the port 他们给你一个环境变量。 Heroku 还在您的应用程序前面安装了负载均衡器。它们将终止 SSL 连接并通过 HTTP 与您的应用程序通信,因此您的应用程序看到的方案将始终是 HTTP。标准 wrap-ssl-redirect
在这种情况下不会很好地工作,我认为它永远不会成功重定向(它会认为用户正在通过 HTTP 连接,即使他们确实被重定向到 HTTPS)。
但是 Heroku 将 x-forwarded-proto
添加到每个请求的 headers 中以解决此问题,因此您可以查看您的客户端使用的协议。在同一个 ring.middleware.ssl
命名空间中是一个 wrap-forwarded-scheme
中间件。
"Middleware that changes the :scheme of the request map to the value present
in a request header. This is useful if your application sits behind a
reverse proxy or load balancer that handles the SSL transport.
The header defaults to x-forwarded-proto."
如果你先用这个包装你的路由,然后用 wrap-ssl-redirect
,它应该正确重定向到 HTTPS。您还可以添加 ring.middleware.ssl/wrap-hsts
以强制执行 HSTS:
(wrap-forwarded-scheme (wrap-ssl-redirect (wrap-hsts app)))
万岁 lib-noir
和它的 wrap-force-ssl
fn。
我只是需要稍微更改一下以满足我的需要(我有一个 SSL 证书。即使我的 clojure 应用程序处理一个以上的域)
这是我的 fn:
(defn wrap-force-ssl
"Almost like in lib-noir.
If the request's scheme is not https [and is for 'secure.'], redirect with https.
Also checks the X-Forwarded-Proto header."
[app]
(fn [req]
(let [headers (:headers req)
host (headers "host")]
(if (or (= :https (:scheme req))
(= "https" (headers "x-forwarded-proto"))
(not= "secure.mydomain.com" host)) ;you might not need this!
(app req)
(noir.response/redirect (str "https://" host (:uri req)) :permanent)))))
感谢 Chris Granger 和朋友们!
我刚刚尝试添加此包装器 (-> routes (wrap-ssl-redirect))
以自动将 http 重定向到 https,但是当我部署到 heroku 时,https://
在我的浏览器和网站中没有变绿未加载。
不是默认的 heroku 端口 443
,它也应该是 wrap-ssl-redirect
函数的默认端口吗?
怎么了?
谢谢!
编辑:
我的代码:
(defn prod-app [routes]
(-> routes
(wrap-keyword-params)
(wrap-params)
(wrap-ssl-redirect)))
(defn -main []
(let [port (Integer/parseInt (get (System/getenv) "PORT" "5000"))]
(jetty/run-jetty (prod-app domain-specific-routes)
{:port port :join? false})))
编辑 2:
我刚找到可以解决我的问题的帖子:
想出了这个 require-https
处理程序 fn:
(defn https-url [request-url]
(str "https://"
(:server-name request-url)
":"
(:server-port request-url)
(:uri request-url)))
(defn require-https
[handler]
(fn [request]
(if (and (= (:scheme request) :http)
(= (get-in request [:headers "host"]) "secure.mydomain.com"))
(ring.util.response/redirect (https-url request))
(handler request))))
但是当我尝试连接到 http://secure.mydomain.com
时,我在浏览器地址栏中看到一个端口 https://secure.mydomain.com:80/
并收到此消息 ERR_SSL_PROTOCOL_ERROR
。
在 Heroku 上,你需要 bind to the port 他们给你一个环境变量。 Heroku 还在您的应用程序前面安装了负载均衡器。它们将终止 SSL 连接并通过 HTTP 与您的应用程序通信,因此您的应用程序看到的方案将始终是 HTTP。标准 wrap-ssl-redirect
在这种情况下不会很好地工作,我认为它永远不会成功重定向(它会认为用户正在通过 HTTP 连接,即使他们确实被重定向到 HTTPS)。
但是 Heroku 将 x-forwarded-proto
添加到每个请求的 headers 中以解决此问题,因此您可以查看您的客户端使用的协议。在同一个 ring.middleware.ssl
命名空间中是一个 wrap-forwarded-scheme
中间件。
"Middleware that changes the :scheme of the request map to the value present in a request header. This is useful if your application sits behind a reverse proxy or load balancer that handles the SSL transport. The header defaults to x-forwarded-proto."
如果你先用这个包装你的路由,然后用 wrap-ssl-redirect
,它应该正确重定向到 HTTPS。您还可以添加 ring.middleware.ssl/wrap-hsts
以强制执行 HSTS:
(wrap-forwarded-scheme (wrap-ssl-redirect (wrap-hsts app)))
万岁 lib-noir
和它的 wrap-force-ssl
fn。
我只是需要稍微更改一下以满足我的需要(我有一个 SSL 证书。即使我的 clojure 应用程序处理一个以上的域)
这是我的 fn:
(defn wrap-force-ssl
"Almost like in lib-noir.
If the request's scheme is not https [and is for 'secure.'], redirect with https.
Also checks the X-Forwarded-Proto header."
[app]
(fn [req]
(let [headers (:headers req)
host (headers "host")]
(if (or (= :https (:scheme req))
(= "https" (headers "x-forwarded-proto"))
(not= "secure.mydomain.com" host)) ;you might not need this!
(app req)
(noir.response/redirect (str "https://" host (:uri req)) :permanent)))))
感谢 Chris Granger 和朋友们!