我有一个使用“安全”cookie的应用程序,并希望测试它的功能,而无需设置复杂的SSL启用开发服务器。有没有办法做到这一点,因为我可以使用./manage.py runserver
测试非加密请求?
答案 0 :(得分:103)
它不像内置的开发服务器那样简单,但是使用stunnel作为浏览器和开发服务器之间的SSLifying中间人并不太难。 Stunnel允许您在计算机上设置一个轻量级服务器,该服务器接受已配置端口上的连接,使用SSL包装它们,并将它们传递给其他服务器。我们将使用它来打开一个stunnel端口(8443),并将它收到的任何流量传递给Django runserver实例。
首先你需要stunnel,它可以是downloaded here,也可以由你的平台的包系统提供(例如:apt-get install stunnel
)。我将使用stunnel的第4版(例如:Ubuntu上的/usr/bin/stunnel4
),版本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
为stunnel创建一个名为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
让我们逐行分解:
使我们刚创建的脚本文件可执行:
chmod a+x runserver
现在,当您想要运行开发服务器时,只需从项目目录中执行./runserver
即可。要试用它,只需将浏览器指向http://localhost:8000以获取正常的HTTP流量,并将https://localhost:8443指向HTTPS流量。请注意,您的浏览器几乎肯定会抱怨所使用的证书,并要求您添加例外或明确指示浏览器继续浏览。这是因为您创建了自己的证书,浏览器不信任它是否说实话。这对于开发来说很好,但显然不会将其用于生产。
不幸的是,在我的机器上,当我按下Ctrl-C时,这个runserver脚本不能很好地退出。我必须手动杀死进程 - 任何人都有建议解决这个问题吗?
感谢Michael Gile的post和django-weave的wiki entry作为参考资料。
答案 1 :(得分:71)
我建议使用django-sslserver包。
PyPI上的当前包仅支持Django 1.5.5版,但已通过5d4664c提交了补丁。通过此修复,系统运行良好,是一种非常简单直接的测试https连接的解决方案。
更新: 自从我发布了我的答案后,上面的提交已经merged进入主分支,并且新的release已被推送到PyPI。因此,不应该为该特定修复指定5d4664c提交。
答案 2 :(得分:52)
与django-sslserver类似,您可以使用RunServerPlus中的django-extensions
它依赖于Werkzeug(因此您可以访问优秀的Werkzeug调试器)和pyOpenSSL(仅适用于ssl模式),因此要安装run:
pip install django-extensions Werkzeug pyOpenSSL
将它添加到项目settings.py文件中的INSTALLED_APPS:
INSTALLED_APPS = (
...
'django_extensions',
...
)
然后您可以使用以下命令在ssl模式下运行服务器:
./manage.py runserver_plus --cert /tmp/cert
这将在/tmp/cert.crt
创建一个证书文件,在/tmp/cert.key
创建一个密钥文件,然后可以在以后的会话中重复使用。
django-extensions中包含一些额外的东西,你可能会发现它们有用,所以值得快速浏览文档。
答案 3 :(得分:12)
注册https://ngrok.com/。您可以使用https进行测试。这可能会帮助那些只想快速测试https的人。
答案 4 :(得分:10)
只需安装
adapter.addFrag(MyFragment.newInstance(model), getString(R.string.sep_prep_base));
在已安装的aps中包含sslserver
sudo pip install django-sslserver
现在您可以运行
INSTALLED_APPS = (...
"sslserver",
...
)
答案 5 :(得分: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)是必需的答案 6 :(得分:4)
一种方法是使用ngrok。
安装ngrok。 下载链接:https://ngrok.com/download
在终端上发出以下命令
ngrok http 8000
它将开始ngrok会话。它将列出两个URL。一个映射到http:// localhost:8000。第二个映射到https:// localhost:8000。请检查以下屏幕截图。使用任一网址。它将映射到您的本地服务器。
第二种方法与@EvanGrim提供的解决方案相同。链接-https://stackoverflow.com/a/8025645/9384511
如果您仅需要几次测试https url,则首选第一种方法。但是,如果您的要求说https是强制性的,那么遵循第二种方法会更好。 我遇到了@EvanGrim解决方案的以下问题
我通过在ssl证书中添加subAltname解决了这些问题。下面是我在没有上述两个问题的情况下运行本地https服务器的步骤。
安装通道。使用的stunnel版本为version4(/ usr / bin / stunnel4)用于ubuntu执行
sudo apt-get install stunnel
在Django项目中创建目录路径。
从/etc/ssl/openssl.cnf或/usr/lib/ssl/openssl.cnf复制openssl.cnf到通道。除非您知道自己在做什么,否则请避免直接编辑它们。
搜索[req]或[req]部分。在req部分中设置
x509_extensions = v3_ca
req_extensions = v3_req
x509_extensions和req_extensions应该存在。如果没有,请添加它。如果有评论,请取消评论。
搜索[v3_req]部分。在此部分添加
subjectAltName = @alt_names
搜索[v3_ca]部分。在此部分添加
subjectAltName = @alt_names
我们需要添加一个新部分alt_names。可以在任何地方添加。我在[v3_ca]部分之后添加了。 对于本地主机和您的IP地址,请添加以下内容:
[alt_names]
DNS.1 = localhost
IP.1 = x.x.x.x
IP.2 = 127.0.0.1
要创建密钥,请执行
openssl genrsa 1024 > stunnel.key
要创建DER编码的证书,请执行第一条命令或第二条命令
如果您直接编辑了/etc/ssl/openssl.cnf或/usr/lib/ssl/openssl.cnf
openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert
如果已在stunnel目录中复制了openssl.cnf。
openssl req -new -x509 -nodes -sha256 -days 365 -key stunnel.key -config openssl.cnf > stunnel.cert
要创建PEM证书,请执行。
cat stunnel.key stunnel.cert > stunnel.pem
为带有以下内容的内容的隧道创建一个名为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
请注意sslVersion基于python解释器使用的OpenSSL版本。我的是OpenSSL 1.1.1。对于此版本,请使用TLSv1.1。找出您的openssl版本并添加相应的版本。 您可以通过执行
来找出OpenSSL版本 python -c "import ssl; print(ssl.OPENSSL_VERSION)"
创建一个名为runserver的脚本,并添加以下内容。该脚本应与manage.py位于同一目录中 该脚本将运行两个stunnel和两个django环境。一个用于http连接,一个用于https连接。 运行服务器不能干净退出的问题(如Evan所述)通过陷阱语句解决,该陷阱语句调用了清理功能。
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
执行
chmod a+x runserver
从您的Django项目执行
./runserver
现在,如果您执行python请求命令,则不会显示subjectAltNames缺少警告。另外,您的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')
我要感谢@EvanGrim提供的解决方案。感谢@ Friek,@ Utku和@dr。 Sybren。根据他们的评论,我实现了清理功能。
答案 7 :(得分:1)
可以使用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
答案 8 :(得分: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.localhost
映射到127.0.0.1
并将django-dev.localhost
添加到ALLOWED_HOSTS
中的settings.py
。在Linux上,您需要将以下行添加到/etc/hosts
:
127.0.0.1 django-dev.localhost
然后,您可以通过在浏览器中转到https://django-dev.localhost
来访问您的开发人员站点(您将需要绕过浏览器的安全警告)。