我如何像使用“ runserver”进行非https连接一样轻松地测试与Django的https连接?


109

我有一个使用“安全” Cookie的应用程序,想要测试其功能而无需设置复杂的启用SSL的开发服务器。有什么办法可以做到这一点,就像我可以使用来测试未加密的请求一样简单./manage.py runserver


您不能仅指定runserver 443来使服务器在端口443上运行吗?
Furbeenator

@Furbeenator:不幸的不是-这只会使服务器在443上使用HTTP,我需要的是实际运行的SSL服务器。
伊万格里姆

Answers:


109

它不像内置的开发服务器那么简单,但是使用stunnel作为浏览器和开发服务器之间的SSLified中间人来达成某种目标并非难事。使用Stunnel,您可以在计算机上设置轻量级服务器,该服务器在已配置的端口上接受连接,使用SSL包装它们,然后将它们传递给其他服务器。我们将使用它打开一个stunnel端口(8443),并将接收到的所有流量传递给Django runserver实例。

首先,您需要一个stunnel,可以在这里下载,也可以由平台的打包系统提供(例如:)apt-get install stunnel。我将使用stunnel的版本4(例如:/usr/bin/stunnel4在Ubuntu上),版本3也可以使用,但是具有不同的配置选项。

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

mkdir stunnel
cd stunnel

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

创建密钥:

openssl genrsa 1024 > stunnel.key

创建使用此密钥的证书(这将询问您将包含在证书中的一堆信息-只需回答对您有帮助的内容即可):

openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert

现在将它们组合到一个单独的文件中,Stunnel将使用该文件进行SSL通信:

cat stunnel.key stunnel.cert > stunnel.pem

为包含以下内容的通道创建一个名为dev_https的配置文件:

pid=

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

[https]
accept=8443
connect=8001
TIMEOUTclose=1

该文件告诉stunnel它需要知道什么。具体来说,您是在告诉它不要使用pid文件,证书文件所在的位置,要使用的SSL版本,应该在前台运行,应该在其日志记录输出以及应该在端口上接受连接8443并将它们穿梭到端口8001。最后一个参数(TIMEOUTclose)告诉它在经过1秒没有活动之后自动关闭连接。

现在弹出您的Django项目目录(其中包含manage.py的目录):

cd ..

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

stunnel4 stunnel/dev_https &
python manage.py runserver&
HTTPS=1 python manage.py runserver 8001

让我们逐行将其分解:

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

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

chmod a+x runserver

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

不幸的是,在我的机器上,当我按下Ctrl-C时,此runserver脚本无法很好地退出。我必须手动终止进程-有人建议解决该问题吗?

感谢Michael Gile的帖子和django-weave的Wiki参考资料。


3
我只是偶然发现了这个答案。一些注意事项:您不必在8001上运行单独的开发实例,也可以使其连接到端口8000。如果希望自动杀死stunnel,请添加一个函数和一个退出陷阱:kill_stunnel(){ kill $ stunnel_pid}陷阱kill_stunnel退出stunnel4 stunnel / dev https和stunnel_pid = $ 1
Friek 2013年

2
使用HTTPS = 1调用第二个实例,这意味着request.is_secure()将报告True。如果不需要,那是对的-您可以将stunnel指向单个实例。
伊万格里姆

如果您运行到不受支持的stunnel fips模式....将fips = no添加到dev_https文件以将其关闭
yeahdixon 2014年

2
我只是在尝试为其他人开发的项目设置站点工作的开发副本时尝试了此操作,但是我得到了"sslVersion = SSLv3": SSLv3 not supported
HenryM '16

@弗里克stunnel_pid=$1不是为我工作,但为我工作stunnel_pid=$!。如何stunnel_pid=$1为您工作?
Utku

86

我建议使用django-sslserver软件包。

PyPI上的当前软件包最多仅支持Django 1.5.5版,但已通过5d4664c提交了补丁。通过此修复程序,系统可以很好地运行,并且是用于测试https连接的非常简单明了的解决方案。

更新:自从我发布答案以来,以上提交已合并到master分支中,并且新版本已推送到PyPI。因此,不需要为该特定修复指定5d4664c提交。


5
这看起来很有希望-我可能必须在这个问题上更新可接受的答案。有人要称重吗?
埃文·格里姆

3
这应该成为一个可以接受的答案,在一个相当复杂的项目中使用了一段时间,这个项目如果不在https上运行就无法工作,并且永远不会出现问题。
simone cittadini

2
效果很好...谢谢!:)
nidHi

5
从Python 3.6.2和Django 1.11.3开始工作。
凤凰城

2
从Python 3.5和Django 1.11开始工作
-Hansel

64

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

它依赖于Werkzeug(因此您可以访问出色的Werkzeug调试器)和pyOpenSSL(仅ssl模式需要),因此可以运行:

pip install django-extensions Werkzeug pyOpenSSL

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

INSTALLED_APPS = (
    ...
    'django_extensions',
    ...
)

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

./manage.py runserver_plus --cert /tmp/cert

这将在处创建一个cert文件/tmp/cert.crt和一个密钥文件,/tmp/cert.key然后可以将其重新用于以后的会话。

django扩展中包含很多额外的东西,您可能会发现它们的使用,因此值得快速浏览一下文档。


2
实际上,这是Django 1.6+的最佳答案,因为django-sslserver不支持新版本的自动重新加载
-Zat42 2015年

调试+激活SSL的最佳答案。
尤达·普拉维拉

我想知道为什么它在Docker容器化应用中不起作用
Roel

@Roel对其进行了快速尝试,它似乎适用于Hello World应用程序。可能是您的基本映像没有必需的依赖项(例如,如果您使用-alpine),或者您可能需要打开IP范围,例如./manage.py runserver_plus --cert /tmp/cert 0.0.0.0:8000
djsutho

FileNotFoundError:[错误2]没有这样的文件或目录: '/tmp\\cert.crt'
马克·安东尼Libres

38

只需安装

sudo pip install django-sslserver

在已安装的aps中包括sslserver

INSTALLED_APPS = (...
"sslserver",
...
)

现在您可以运行

 python manage.py runsslserver 0.0.0.0:8888

2
最干净的解决方案!
SexyBeast

确实是一个干净的解决方案,但是由于某些原因,它非常慢
Bhanu Tez

嗯,Chrome正在警告该证书无效。
zerohedge

@zerohedge仅用于开发,所以没关系。
Sharpless512

这非常优雅-但是有什么解决方案可以用来测试安全连接吗?例如,如果要针对Facebook Graph API进行测试? developers.facebook.com/docs/graph-api/webhooks#setup
frednikgohar

14

注册到https://ngrok.com/。您可以使用https进行测试。这可能对只想快速测试https的人有所帮助。


6
对于快速测试,这是一个很好的解决方案。而且我不需要注册任何东西,只需下载并运行./ngrok http 8000,8000是我的本地主机端口。
GavKilbride '16

4

对于那些寻找stunnel选项的前台版本以进行调试的用户:

stunnel.pem是在Evan Grimm的最高投票答案中生成的证书。

在端口443上侦听所有本地接口,并转发到localhost上的端口80

sudo stunnel -f -p stunnel.pem -P ~/stunnel.pid -r localhost:80 -d 443

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



2

可以用socat一行完成:

socat openssl-listen:8443,fork,reuseaddr,cert=server.pem,verify=0 tcp:localhost:8000

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

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


0

使用Nginx之类的代理而不是Django处理SSL / TLS。可以将Nginx设置为侦听端口443,然后将请求转发到Django开发服务器(通常为http://127.0.0.1:8000)。Nginx的配置可能如下所示:

server {
    listen 443 ssl;
    server_name django-dev.localhost;

    ssl_certificate /etc/ssl/certs/nginx_chain.pem;
    ssl_certificate_key /etc/ssl/private/nginx.pem;    

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_set_header Host $host;
    }
}

您还需要映射django-dev.localhost127.0.0.1并添加django-dev.localhostALLOWED_HOSTSsettings.py。在Linux上,您需要将以下行添加到/etc/hosts

127.0.0.1   django-dev.localhost

然后,您可以通过https://django-dev.localhost在浏览器中进入来访问您的开发人员站点(您将需要绕过浏览器的安全警告)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.