我如何使用'runserver'轻松测试与Django的https连接?

Eva*_*rim 95 django ssl https

我有一个使用"安全"cookie的应用程序,并希望测试它的功能,而无需设置复杂的SSL启用开发服务器.有没有办法做到这一点就像我可以使用测试非加密请求一样./manage.py runserver

Eva*_*rim 105

它并不内置的开发服务器那么简单,但使用stunnel作为浏览器和开发服务器之间的SSLifying中间人并不太难.Stunnel允许您在计算机上设置一个轻量级服务器,该服务器接受已配置端口上的连接,使用SSL包装它们,并将它们传递给其他服务器.我们将使用它来打开一个stunnel端口(8443)并将它接收到的任何流量传递给Django runserver实例.

首先,您需要可以在此处下载的 stunnel,或者可以由您的平台的软件包系统提供(例如:)apt-get install stunnel.我将使用stunnel的第4版(例如:/usr/bin/stunnel4在Ubuntu上),版本3也可以使用,但有不同的配置选项.

首先在Django项目中创建一个目录,以保存必要的配置文件和SSLish.

mkdir stunnel
cd stunnel
Run Code Online (Sandbox Code Playgroud)

接下来,我们需要创建一个用于SSL通信的本地证书和密钥.为此,我们转向openssl.

创建密钥:

openssl genrsa 1024 > stunnel.key
Run Code Online (Sandbox Code Playgroud)

创建使用此密钥的证书(这将询问您将包含在证书中的大量信息 - 只需回答任何对您感觉良好的信息):

openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert
Run Code Online (Sandbox Code Playgroud)

现在将这些组合成一个stunnel将用于其SSL通信的文件:

cat stunnel.key stunnel.cert > stunnel.pem
Run Code Online (Sandbox Code Playgroud)

为stunnel创建一个名为dev_https的配置文件,其中包含以下内容:

pid=

cert = stunnel/stunnel.pem
sslVersion = SSLv3
foreground = yes
output = stunnel.log

[https]
accept=8443
connect=8001
TIMEOUTclose=1
Run Code Online (Sandbox Code Playgroud)

该文件告诉stunnel它需要知道什么.具体来说,你告诉它不要使用pid文件,证书文件在哪里,使用什么版本的SSL,它应该在前台运行,它应该记录它的输出,以及它应该接受端口上的连接8443并将它们连接到端口8001.最后一个参数(TIMEOUTclose)告诉它在1秒钟后没有活动时自动关闭连接.

现在回到Django项目目录(其中包含manage.py):

cd ..
Run Code Online (Sandbox Code Playgroud)

在这里,我们将创建一个名为runserver的脚本,它将运行stunnel和两个django开发服务器(一个用于普通连接,一个用于SSL连接):

stunnel4 stunnel/dev_https &
python manage.py runserver&
HTTPS=1 python manage.py runserver 8001
Run Code Online (Sandbox Code Playgroud)

让我们逐行打破这个:

  • 第1行:启动stunnel并将其指向我们刚刚创建的配置文件.这有stunnel侦听端口8443,包装它在SSL中接收的任何连接,并将它们传递到端口8001
  • 第2行:启动一个普通的Django runserver实例(在端口8000上)
  • 第3行:启动另一个Django runserver实例(在端口8001上)并配置它以将所有传入连接视为使用HTTPS执行它们.

使我们刚刚创建的脚本文件可执行:

chmod a+x runserver
Run Code Online (Sandbox Code Playgroud)

现在,当您想运行开发服务器时,只需./runserver从项目目录执行即可.要试用它,只需将浏览器指向http:// localhost:8000以获取正常的HTTP流量,将https:// localhost:8443指向HTTPS流量.请注意,您的浏览器几乎肯定会抱怨所使用的证书,并要求您添加例外或明确指示浏览器继续浏览.这是因为您创建了自己的证书,浏览器不信任它说实话的真相.这对于开发来说很好,但显然不会将其用于生产.

不幸的是,在我的机器上,当我按下Ctrl-C时,这个runserver脚本不能很好地退出.我必须手动杀死进程 - 任何人都有建议解决这个问题?

感谢Michael Gile的帖子和django-weave的wiki条目作为参考资料.

  • 我只是偶然发现了这个答案.一些评论:您不一定需要在8001上运行单独的开发实例,您也可以让它连接到端口8000.如果您希望自动终止stunnel,请添加一个函数和一个退出陷阱:kill_stunnel(){ kill $ stunnel_pid} trap kill_stunnel exit stunnel4 stunnel/dev https&stunnel_pid = $ 1 (3认同)
  • 使用HTTPS = 1调用第二个实例,这意味着`request.is_secure()`将报告'True`.如果你不需要那么你就是对的 - 你可以在单个实例上指出stunnel. (2认同)
  • 我刚刚尝试过这个,因为我正在尝试为其他人开发的项目设置站点工作的开发副本,但我收到了`"sslVersion = SSLv3": SSLv3 not supported`。 (2认同)

dev*_*rey 77

我建议使用django-sslserver包.

PyPI上的当前包仅支持Django 1.5.5版本,但是已经通过5d4664c提交了补丁.通过此修复,系统运行良好,是一种非常简单直接的测试https连接的解决方案.

更新:自从我发布了我的答案后,上面的提交已合并到主分支中,并且新版本已被推送到PyPI.因此,不应该为该特定修复指定5d4664c提交.

  • 这看起来很有希望 - 我可能不得不更新这个接受的答案.还有其他人想要权衡吗? (5认同)
  • 适用于Python 3.6.2和Django 1.11.3. (5认同)
  • 这应该成为公认的答案,在一个相当复杂的项目中使用了一段时间,如果没有在https上运行并且从未遇到过问题,它就无法工作. (3认同)
  • 适用于 Python 3.5 和 Django 1.11 (3认同)
  • 效果很好......谢谢!:) (2认同)

djs*_*tho 59

类似Django的sslserver你可以使用RunServerPlusDjango的扩展

它依赖于Werkzeug(所以你可以访问优秀的Werkzeug调试器)和pyOpenSSL(只有ssl模式需要)才能安装run:

pip install django-extensions Werkzeug pyOpenSSL
Run Code Online (Sandbox Code Playgroud)

将其添加到项目settings.py文件中的INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    'django_extensions',
    ...
)
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下命令在ssl模式下运行服务器:

./manage.py runserver_plus --cert /tmp/cert
Run Code Online (Sandbox Code Playgroud)

这将创建一个cert文件/tmp/cert.crt和一个密钥文件,/tmp/cert.key然后可以在以后的会话中重复使用该文件.

django-extensions中包含一些额外的东西,您可能会发现它们的使用,因此值得快速浏览一下文档.

  • 实际上是Django 1.6+的最佳答案,因为django-sslserver不支持新版本的自动重载 (2认同)

Rya*_*der 16

只是安装

sudo pip install django-sslserver
Run Code Online (Sandbox Code Playgroud)

在已安装的aps中包含sslserver

INSTALLED_APPS = (...
"sslserver",
...
)
Run Code Online (Sandbox Code Playgroud)

现在你可以跑了

 python manage.py runsslserver 0.0.0.0:8888
Run Code Online (Sandbox Code Playgroud)

  • 最干净的解决方案! (2认同)

Nei*_*eil 12

注册https://ngrok.com/.您可以使用https进行测试.这可能会帮助那些只想快速测试https的用户.

  • 对于快速测试,这是一个很好的解决方案.我没有注册任何东西,只需下载并运行./ngrok http 8000,8000是我的localhost端口. (4认同)

ABN*_*ABN 12

一种方法是使用 ngrok。

  1. 安装 ngrok。下载链接:https : //ngrok.com/download

  2. 在终端上发出以下命令

    ngrok http 8000
    
    Run Code Online (Sandbox Code Playgroud)

它将启动 ngrok 会话。它将列出两个网址。一个映射到 http://localhost:8000。第二个映射到 https://localhost:8000。请检查下面的屏幕截图。使用任一网址。它将映射到您的本地服务器。

示例 ngrok 会话屏幕截图


第二种方法是根据@EvanGrim 提供的解决方案。链接 - /sf/answers/561795181/

如果您只需要测试 https url 几次,则首选第一种方法。但是,如果您的要求说 https 是强制性的,那么您最好遵循第二种方法。我在@EvanGrim 解决方案中遇到了以下问题

  1. 通过请求访问 https url 时,您将收到 subAltNames 丢失警告。这应该不是问题。您的网址应该可以正常工作。
  2. 您将无法通过 android volley 访问 https url。它会抛出错误 - 您的 ip 或 localhost 未验证。类似的东西。

我通过将 subAltname 添加到 ssl 证书解决了这些问题。以下是我在没有上述两个问题的情况下运行本地 https 服务器的步骤。

  1. 安装隧道。使用的 stunnel 版本是 version4(/usr/bin/stunnel4) 对于 ubuntu 执行

     sudo apt-get install stunnel
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在 Django 项目中创建目录 stunnel。

  3. 将 openssl.cnf 从 /etc/ssl/openssl.cnf 或 /usr/lib/ssl/openssl.cnf 复制到 stunnel。避免直接编辑它们,除非您知道自己在做什么。

    1. 搜索 [ req ] 或 [req] 部分。在 req 部分设置

       x509_extensions = v3_ca 
       req_extensions = v3_req 
      
      Run Code Online (Sandbox Code Playgroud)

      x509_extensions 和 req_extensions 应该存在。如果没有,请添加它。如果有评论,请取消评论。

    2. 搜索 [v3_req] 部分。在本节中添加

       subjectAltName = @alt_names
      
      Run Code Online (Sandbox Code Playgroud)
    3. 搜索 [v3_ca] 部分。在本节中添加

       subjectAltName = @alt_names
      
      Run Code Online (Sandbox Code Playgroud)
    4. 我们需要添加一个新部分 alt_names。这可以添加到任何地方。我在 [v3_ca] 部分之后添加。对于本地主机和您的 ip 地址添加如下:

       [alt_names]
       DNS.1 = localhost
       IP.1 = x.x.x.x
       IP.2 = 127.0.0.1
      
      Run Code Online (Sandbox Code Playgroud)
  4. 创建密钥执行

     openssl genrsa 1024 > stunnel.key
    
    Run Code Online (Sandbox Code Playgroud)
  5. 要创建 DER 编码的证书,请执行第一个或第二个命令

    1. 如果你直接编辑过 /etc/ssl/openssl.cnf 或 /usr/lib/ssl/openssl.cnf

       openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert
      
      Run Code Online (Sandbox Code Playgroud)
    2. 如果您在 stunnel 目录中复制了 openssl.cnf。

       openssl req -new -x509 -nodes -sha256 -days 365 -key stunnel.key -config openssl.cnf > stunnel.cert
      
      Run Code Online (Sandbox Code Playgroud)
  6. 要创建 PEM 编码证书,请执行。

     cat stunnel.key stunnel.cert > stunnel.pem
    
    Run Code Online (Sandbox Code Playgroud)
  7. 使用以下内容为 stunnel 创建一个名为 dev_https.config 的配置文件。

     #not to use pid
     pid=
     #path of certificate file
     cert = stunnel/stunnel.pem
     #version of SSL to use
     sslVersion = TLSv1.1
     foreground = yes
     #log output path
     output = stunnel.log
    
     [https]
     #listen on port 8443
     accept=8443
     #tunnel the connection to port 8001
     connect=8001
     # and close connection automatically after one second
     TIMEOUTclose=1
    
    Run Code Online (Sandbox Code Playgroud)

    请注意 sslVersion 基于 python 解释器使用的 OpenSSL 版本。我的是 OpenSSL 1.1.1。对于此版本,请使用 TLSv1.1。找出你的openssl版本并添加相应的版本。您可以通过执行找到 OpenSSL 版本

     python -c "import ssl; print(ssl.OPENSSL_VERSION)"
    
    Run Code Online (Sandbox Code Playgroud)
  8. 创建一个名为 runserver 的脚本并添加以下内容。此脚本应与 manage.py 位于同一目录中。此脚本将运行两个 stunnel 和两个 django 环境。一种用于 http 连接,一种用于 https 连接。runserver 不干净退出的问题(如Evan 提到的)通过调用cleanup 函数的trap 语句解决。

     stunnel4 stunnel/dev_https.config &
     stunnel_pid=$!
     echo "stunnel pid: $stunnel_pid"
     python manage.py runserver 0.0.0.0:8000 &
     py_server_bg=$!
     echo "BG py server pid: $py_server_bg"
     HTTPS=1 python manage.py runserver 0.0.0.0:8001
    
     function cleanup()
     {
       echo "Cleaning up"
       kill $stunnel_pid
       kill $py_server_bg
       echo "Cleaned"
     }
    
     trap cleanup EXIT
    
    Run Code Online (Sandbox Code Playgroud)
  9. 执行

     chmod a+x runserver
    
    Run Code Online (Sandbox Code Playgroud)
  10. 从你 Django 项目执行

    ./runserver
    
    Run Code Online (Sandbox Code Playgroud)
  11. 现在,如果您执行 python requests 命令,将不会显示 subjectAltNames missing 警告。您的 android volley https 请求也可以正常执行。

    data = {'login_id':'someid'}
    headers = {'content-type': 'application/json'}
    url = "https://localhost:8443/myauth/check-id/"
    r=requests.post(url, data=json.dumps(data), headers=headers,verify='stunnel/stunnel.pem')
    
    Run Code Online (Sandbox Code Playgroud)

我要感谢@EvanGrim 的解决方案。感谢@Friek、@Utku 和@dr。西布伦。根据他们的评论,我实现了清理功能。


uri*_*i.z 6

可以使用 socat 一行完成:

socat openssl-listen:8443,fork,reuseaddr,cert=server.pem,verify=0 tcp:localhost:8000
Run Code Online (Sandbox Code Playgroud)

,其中 8443 是侦听传入 HTTPS 连接的端口,server.pem 是自签名服务器证书,localhost:8000 是照常启动的调试 HTTP 服务器。

更多详细信息:http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html


小智 5

对于那些出于调试目的而寻找 stunnel 选项前景版本的人:

stunnel.pem 是按照 Evan Grimm 得票最高的答案生成的证书。

侦听端口 443 上的所有本地接口并转发到本地主机上的端口 80

sudo stunnel -f -p stunnel.pem -P ~/stunnel.pid -r localhost:80 -d 443
Run Code Online (Sandbox Code Playgroud)

仅对于 1024 以下的传入端口 (-d [host:]port) 才需要 sudo