Clojure Compojure Ring和https

时间:2014-07-22 20:18:10

标签: https clojure ring compojure

我正在使用Clojure(ring和compojure)来构建一个Web应用程序,我不知道从哪里开始使用https。我有一个需要保护的注册和登录,然后一旦他们通过身份验证,他们就需要保持https状态。

我似乎找不到一个关于一般设置https或专门设置clojure应用程序的好教程。

我找到了这个答案:How do you enable https and http->https redirects in ring / compojure

这是否意味着我可以编写我的compojure应用程序,好像没有https并且让nginx坐在前面并为我处理所有这些?

6 个答案:

答案 0 :(得分:7)

是的,标准程序是让nginx在基于环网的webapp前面充当 reverse proxy 。这被认为是安全的,并且更容易维护,因为它更标准。我知道的每个clojure based site都是这样做的。

答案 1 :(得分:3)

通常,应用程序级代码不关心它是HTTPS还是HTTP。大多数情况下,它由应用程序服务器或其前面的代理提供。如果您熟悉,您的选择与Java世界中的选择非常相似。

  1. 如果您正在使用Jetty适配器,它有ssl?ssl-port个选项。请参阅docs hererelated blog post here

  2. 您可以在纯HTTP中运行您的Ring应用程序,并在其前面放置一个代理,如Nginx或Apache。代理将实现HTTPS并将请求作为普通HTTP转发到您的应用程序。

答案 2 :(得分:3)

反向代理方法似乎确实是最常见的选择。然而,作为一个“实验”,我研究了使用https来使用ring,jetty compojure等。这并不难。

  1. 首先,您需要使用keytool生成自签名证书并将其安装到新的密钥库中。 keytool文档非常好,可以引导您完成此过程。请注意,如果您使用自签名证书,则需要为大多数浏览器添加例外规则,以表明您信任该证书。

  2. 将创建的密钥库文件复制到项目树的根目录

  3. 更新jetty配置参数以指定ssl,ssl-port,密钥库文件和密钥库密码。

  4. 将ring / ring-defaults包添加到project.clj

  5. 使用secure-site-defaults配置选项添加wrap-defaults中间件以强制https连接,即将http连接重定向到https。

  6. 这不是我建议用于生产的设置,但我发现它比在开发等时配置ngix更简单。最难的部分是通过keytool进程。但是,只需按照文档和示例提供的内容就足够了,只要您不允许yoruself被所有选项所淹没 - 只需保持简单。

    这样的东西
    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
    

答案 3 :(得分:1)

另一个解决方案是尝试使用nginx-clojure(http://nginx-clojure.github.io),您可以通过它直接在nginx上部署ring app。 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服务器配置的更多详细信息

答案 4 :(得分:1)

非常简单。如果要在Web应用程序中启用HTTPS支持,请执行以下操作:

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

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

    {   :SSL?真正   :ssl-port 8443   :keystore“jks文件的路径”   :密钥密码“密钥库密码” }

  3. 启动服务器。现在,您的网络应用已启用HTTPS。

  4. 当我尝试使用社交媒体代码测试我的登录时,我遇到了类似的问题,显然必须通过HTTPS进行身份验证,这对我来说很有用。

答案 5 :(得分:0)

您可以设置强制所有请求使用SSL的Ring中间件。一种简单的方法是使用ring-defaults库。

来自ring-defaults文档:

  

中间件包含四种配置       - api-defaults
      - 网站默认值
      - secure-api-defaults
      - 安全站点默认值
  ...
  “安全”默认强制SSL。未加密的HTTP URL被重定向到等效的HTTPS URL,并发送各种标头和标志,以防止浏览器通过不安全的通道发送敏感信息。

另请注意:

  • 为了在没有SSL的情况下启用本地开发,您可以根据环境变量设置您使用的环默认设置。 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的应用程序。