我正在开发一个带有Bottle的RESTful Web服务,可能很快就会迁移到Werkzeug。我想实现一个基于私钥/公钥对的auth方案,其中服务器只需要存储公共部分,而用户保留私有部分。在访问时,服务器将要求访问者使用服务器可以验证并与公钥部分相关的私钥来执行动作。一旦成功,例如生成可以使用一段时间的令牌。为Werkzeug或Bottle实现类似的东西的路径是什么?我可以使用的任何项目/示例吗?
答案 0 :(得分:3)
我相信,这里最好的选择是将责任转移到加密技术上。 Web服务器和CA(证书颁发机构)都很好。
基本上,他们可以
我们使用这种机制来验证第三方支付服务(对不起,私有代码),并且还有一个plugin to Redmine提供相同的客户端授权机制,我们也使用它(当然,它是Ruby ,但它也是一个有效的证据,证明这些服务可以在野外找到。)
为了让事情顺利进行,您只需要
以下是easyrsa,nginx,uWsgi和werkzeug的一个小例子
配置CA
easyrsa工具包是OpenVPN安装的一部分。可以使用OpenSSL“raw”命令或PyOpenSSL,但easyrsa至少在概念阶段是方便和合适的。
cp -a /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/nginx/easyrsa
cd /etc/nginx/easyrsa && source vars && ./clean-all
创建CA
./build-ca
创建服务器证书
./build-key --server server
创建客户证书。
./build-key-pkcs12 client1
在上面的示例中,您将同时创建客户端密钥及其对应的公共部分(证书),但良好实践假定您已签署客户端证书请求,并且无权访问秘密部分。
有些服务会为您生成一对密钥+证书,然后在下载页面上写一条消息,例如“这是您下载密钥的唯一机会。我们不存储它,所以无法下载后“。
此外,此命令还会创建一个带有加密密钥和证书的PKCS12文件,这对于导入浏览器非常方便。
配置nginx
首先,我们应该创建一对“服务器证书+ ca证书”,作为我们的CA自签名:
cat keys/server.crt keys/ca.crt > keys/server_and_ca.crt
然后可以应用以下配置:
server {
listen 443;
location / {
# Here we define the name and the contents of the WSGI variable to pass to service
uwsgi_param SSL_CLIENT_ID $ssl_client_s_dn;
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
# SSL support
ssl on;
ssl_protocols SSLv3 TLSv1;
ssl_certificate easyrsa/keys/ca_and_server.crt;
ssl_certificate_key easyrsa/keys/server.key;
# We don't accept anyone without correct client certificate
ssl_verify_client on;
# The CA we use to verify client certificates
ssl_client_certificate easyrsa/keys/ca.crt;
}
确保您对/ etc / nginx / easyrsa目录具有正确的权限,并且只有root和nginx才能访问密钥。
撰写Werkzeug申请
python部分很简单。只需从WSGI环境中读取变量SSL_CLIENT_ID。
文件sample.py
from werkzeug.wrappers import Response
def application(environ, start_response):
text = 'Hello, your certificate id is %s\n' % environ.get('SSL_CLIENT_ID', '(unknown)')
response = Response(text, mimetype='text/plain')
return response(environ, start_response)
使用uwsgi服务器启动服务:uwsgi -w sample:application --socket 127.0.0.1:5000
测试您的安装
使用curl进行测试很容易
$ curl --cert keys/client1.crt --key keys/client1.key --cacert keys/ca.crt https://localhost/
Hello, your certificate id is /C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=client1/name=changeme/emailAddress=mail@host.domain