Clojure Compojure Ring and https

6
我正在使用Clojure(ring和compojure)构建Web应用程序,但我不知道如何开始使用https。我有一个需要保护的注册和登录,一旦经过身份验证,它们就需要保持在https中。
我似乎找不到关于设置https的好教程,无论是一般还是针对Clojure应用程序的。
我找到了这个答案:How do you enable https and http->https redirects in ring / compojure 那是否意味着我可以像没有https一样编写我的compojure应用程序,并让nginx在前面处理所有内容?
6个回答

8

是的,标准流程是让nginx充当环形web应用程序前面的反向代理。这被认为是安全的,更易于维护,因为它更加标准化。我所知道的每个基于Clojure的站点都是这样做的。


6
反向代理方法似乎是最常用的选项。然而,作为一个“实验”,我尝试使用仅有的ring、jetty compojure等工具来实现https协议。这并不难。
第一步,需要使用keytool生成自签名证书,并将其安装到新的keystore中。Keytool文档非常好,可以引导您完成此过程。请注意,如果您使用自签名证书,则需要在大多数浏览器中添加例外规则以表示您信任该证书。
将创建的keystore文件复制到项目树的根目录下。
更新jetty配置参数以指定ssl、ssl-port、keystore文件和keystore密码。
在project.clj中添加ring/ring-defaults包。
添加wrap-defaults中间件以使用secure-site-defaults配置选项强制使用https连接,即将http连接重定向到https。
这不是我推荐用于生产环境的设置,但我发现它比在开发等过程中同时配置ngix要简单得多。最困难的部分是通过keytool流程。但是,只需按照文档和示例操作即可,您就足够了,只要您不让自己被所有选项压倒 - 保持简单即可。
例如:
keytool -genkeypair \
        -keystore $SSL_DIR/$KS_NAME \
        -keypass $PASSWORD \
        -storepass $PASSWORD \
        -keyalg RSA -keysize 2048 \
        -alias root \
        -ext bc:c \
        -dname "$ROOT_CN"

echo "CA Key"
keytool -genkeypair \
        -keystore $SSL_DIR/$KS_NAME \
        -alias ca \
        -ext bc:c \
        -keypass $PASSWORD \
        -keyalg RSA -keysize 2048 \
        -storepass $PASSWORD \
        -dname "$CA_CN"

echo "Server Key"
keytool -genkeypair \
        -keystore $SSL_DIR/$KS_NAME \
        -alias server \
        -keypass $PASSWORD \
        -storepass $PASSWORD \
        -keyalg RSA -keysize 2048 \
        -dname "$SERVER_CN"

echo "Root Cert"
keytool -keystore $SSL_DIR/$KS_NAME \
        -storepass $PASSWORD \
        -alias root \
        -exportcert \
        -rfc > $SSL_DIR/root.pem

echo "CA Cert"
keytool -storepass $PASSWORD \
        -keystore $SSL_DIR/$KS_NAME \
        -certreq \
        -alias ca | keytool -storepass $PASSWORD \
                            -keystore $SSL_DIR/$KS_NAME \
                            -gencert \
                            -alias root \
                            -ext BC=0 \
                            -rfc > $SSL_DIR/ca.pem

echo "Import CA cert"
keytool -keystore $SSL_DIR/$KS_NAME \
        -storepass $PASSWORD \
        -importcert \
        -alias ca \
        -file $SSL_DIR/ca.pem

echo "Server Cert"
keytool -storepass $PASSWORD \
        -keystore $SSL_DIR/$KS_NAME \
        -certreq \
        -alias server | keytool -storepass $PASSWORD \
                                -keystore $SSL_DIR/$KS_NAME \
                                -gencert \
                                -alias ca \
                                -rfc > $SSL_DIR/server.pem



echo "Import Server Cert"
cat $SSL_DIR/root.pem $SSL_DIR/ca.pem $SSL_DIR/server.pem | \
    keytool -keystore $SSL_DIR/$KS_NAME \
            -storepass $PASSWORD \
            -keypass $PASSWORD \
            -importcert \
            -alias server

4
通常应用程序级别的代码不关心是HTTPS还是HTTP。大多数情况下,应用程序服务器或代理在前面提供它。如果您熟悉,那么您的选择与Java世界中的选择基本相同。
  1. 如果您正在使用Jetty适配器,则具有ssl?和ssl-port选项。请参见文档在此以及相关博客文章在此
  2. 您可以在纯HTTP中运行Ring应用程序,并在其前面放置诸如Nginx或Apache之类的代理。代理将实现HTTPS并将请求作为纯HTTP转发到您的应用程序。

1
您可以设置Ring中间件,强制所有请求使用SSL。一种简单的方法是使用ring-defaults库。
来自ring-defaults文档:
引用: 有四个配置包含在中间件中 - api-defaults - site-defaults - secure-api-defaults - secure-site-defaults ... "secure"默认值强制使用SSL。未加密的HTTP URL将重定向到相应的HTTPS URL,并发送各种标头和标志以防止浏览器通过不安全的通道发送敏感信息。
另请注意:
  • 为了在没有SSL的情况下启用本地开发,可以基于环境变量设置使用哪个ring-defaults集合。Environ可以帮助您完成此操作。
  • 为了使SSL在负载均衡器或代理后工作,必须在ring-defaults映射中将:proxy设置为true。
这是一个大致的想法:
(ns my-app
  (:require [ring.middleware.defaults :refer :all]
            [environ.core :refer [env]]))

(defroutes app-routes
  (GET "/" [] "home page"))

(def app
  (-> app-routes
    (wrap-defaults (if (= (env :environment) "dev")
                     site-defaults
                     (assoc secure-site-defaults :proxy true))))

我不了解nginx,但我已经实现了在Heroku部署的应用程序。

1

另一个解决方案是尝试使用nginx-clojure (http://nginx-clojure.github.io),通过它您可以直接在nginx上部署ring应用程序。nginx可以更高效地处理https。

以下是关于nginx.conf的示例:

http {

### jvm dynamic library path
jvm_path '/usr/lib/jvm/java-7-oracle/jre/lib/amd64/server/libjvm.so';

### my app jars e.g. clojure-1.5.1.jar , groovy-2.3.4.jar ,etc.
jvm_var my_other_jars 'my_jar_dir/clojure-1.5.1.jar';

### my app classpath, windows user should use ';' as the separator
jvm_options "-Djava.class.path=jars/nginx-clojure-0.3.0.jar:#{my_other_jars}";

server {
  listen 80 default deferred;
  server_name example.com;

  ###redirect to https
  rewrite ^/(.+) https://example.com/$1 permanent;
}

server {
  listen 443 ssl;
  server_name example.com;

  ssl_certificate /opt/mycert/my-unified.crt;
  ssl_certificate_key /opt/mycert/my.key;


  location /myapp {
     content_handler_name 'my/ringapp';
  }

}

}

你可以从http://nginx.org/en/docs/http/configuring_https_servers.html获取有关SSL服务器配置的更多详细信息。


0

非常简单。如果您想在Web应用程序中启用HTTPS支持,请按照以下步骤操作:

  1. 使用名为keytool的Linux工具生成Java KeyStore(.jks)文件。

  2. 在project.clj文件的环形映射中添加以下内容:

    { :ssl? true :ssl-port 8443 :keystore "jks文件路径" :key-password "密钥库密码" }

  3. 启动服务器。现在您的Web应用程序已启用HTTPS。

当我尝试使用社交媒体代码进行登录验证时,遇到了类似的问题,这个方法对我很有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接