【问题标题】:How to implement private/public apikey with werkzeug/bottle?如何使用 werkzeug/bottle 实现私有/公共 apikey?
【发布时间】:2012-11-24 11:19:02
【问题描述】:

我正在使用 Bottle 开发一个 RESTful Web 服务,可能很快就会迁移到 Werkzeug。我想实现一个基于私钥/公钥对的身份验证方案,其中服务器只需要存储公共部分,而用户保留私有部分。在访问时,服务器将要求访问者使用服务器可以验证并与公钥部分相关的私钥执行操作。成功后,例如生成一个可以使用一段时间的令牌。为 Werkzeug 或 Bottle 实现类似的路径是什么?我可以使用的任何项目/示例?

【问题讨论】:

  • 是否应该假设非对称算法(即私钥/公钥对)是不可避免的要求?如果是这样,那么看起来签名 cookie 不是一个选项,因为它们使用对称加密。

标签: python rest public-key-encryption bottle werkzeug


【解决方案1】:

我相信,最好的选择是将使用密码学的责任转移到其他事情上。 Web 服务器和 CA(认证机构)都很好用。

基本上,他们完全可以

  1. 确保连接安全
  2. 确保客户端使用由有效(例如,您的)CA 签名的证书
  3. 确保证书未被吊销
  4. 向您的应用程序提供您需要的唯一信息:远程方的标识符

我们使用这种机制来验证第三方支付服务(对不起,私人代码),还有一个plugin to Redmine提供相同的客户端授权机制,我们也使用它(当然是Ruby,但是这也是可以在野外找到此类服务的有效证据。)

为了让事情顺利进行,你所需要的只是

  1. 配置您的 CA。
  2. 配置您的网络服务器以确保它接受您的权威机构颁发的证书,并且只接受这些证书,并将客户端 ID 进一步传递给您的应用。
  3. 确保您的应用程序可以从请求中提取客户端标识符。

下面是easyrsa、nginx、uWsgi和werkzeug的一个小例子

配置 CA

easyrsa 工具包是 OpenVPN 安装的一部分。可以使用 OpenSSL“原始”命令或 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;
}

有关配置选项的更多信息,请访问 herehere

确保您对 /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

【讨论】:

  • 谢谢,这是一个有趣的方法和很好的指导。我是否正确假设几乎所有平台上的 python 安装都支持以这种方式执行 ssl 请求? (参见例如stackoverflow.com/questions/1875052/…
  • 很遗憾,我无法确定。然而我认为它应该适用于 OpenSSL 工作的所有平台。 Python ssl module documentation 表示“只要在该平台上安装了 OpenSSL,它就可以在所有现代 Unix 系统、Windows、Mac OS X 以及可能的其他平台上使用。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
  • 2019-08-26
  • 2017-03-14
  • 1970-01-01
相关资源
最近更新 更多