python3使用Tornado的搭建HTTPS服务

系统 534 0

前言

最近需要使用https搭建一个api 故简单记录一下搭建过程
搭建http的服务简单快捷,这里就不做其他介绍

有关https的原理 请参考
图解HTTPS

环境搭建(非必须)

这个环境其实不是必须的,我再搭建的时候,并没有安装这个环境,因为我的linux服务器自带的有了,可能 是在安装其他软件的时候再带安装上去了,所以可以自我检测一下。

一、 安装OpenSSL

  1. OpenSSL 介绍
    OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
    SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。SSL能使用户/服务器应用之间的通信不被攻击者窃听,并且始终对服务器进行认证,还可选择对用户进行认证。SSL协议要求建立在可靠的传输层协议(TCP)之上。

  2. OpenSSL 安装
    安装openssl

                    
                      $ 
                      
                        sudo
                      
                      
                        apt-get
                      
                      
                        install
                      
                       openssl      
    
                    
                  

    安装openssl开发库

                    
                      	$ 
                      
                        sudo
                      
                      
                        apt-get
                      
                      
                        install
                      
                       libssl-dev    
    
                    
                  

    编辑器使用 bless 十六进制编辑器,需预先安装

                    
                      $ 
                      
                        sudo
                      
                      
                        apt-get
                      
                      
                        install
                      
                       bless
    
                    
                  
  3. 获取 openssl.cnf (必须步骤)
    去这个目录下 /usr/lib/ssl/openssl.cnf 拷贝出 openssl.cnf
    这是 openssl 的配置文件,下面生成证书及签名的时候 我们将用到这个文件
    可能不同的os 此文件的位置不同,我的目录是在 /etc/pki/CA/

            
              openssl
              
                .
              
              cnf简单释义
vi 
              
                /
              
              usr
              
                /
              
              lib
              
                /
              
              ssl
              
                /
              
              openssl
              
                .
              
              cnf

              
                127
              
              
                [
              
               req_distinguished_name 
              
                ]
              
              
                128
              
               countryName                    
              
                =
              
               Country 
              
                Name
              
              
                (
              
              
                2
              
               letter code
              
                )
              
              ##国家名,
              
                2
              
              个字母代码简称

              
                129
              
               countryName_default            
              
                =
              
              
                CN
              
                ##中国就是
              
                CN
              
              
                130
              
               countryName_min                
              
                =
              
              
                2
              
              
                131
              
               countryName_max                
              
                =
              
              
                2
              
              
                132
              
              
                133
              
               stateOrProvinceName            
              
                =
              
               State or Province 
              
                Name
              
              
                (
              
              full name
              
                )
              
              ##州或省的名字

              
                134
              
               stateOrProvinceName_default    
              
                =
              
               beijing

              
                135
              
              
                136
              
               localityName                    
              
                =
              
               Locality 
              
                Name
              
              
                (
              
              eg
              
                ,
              
               city
              
                )
              
                ##本地城市名

              
                137
              
               localityName_default            
              
                =
              
              beijing

              
                138
              
              
                0.
              
              organizationName              
              
                =
              
               Organization 
              
                Name
              
              
                (
              
              eg
              
                ,
              
               company
              
                )
              
               ##
              
                组织
              
              
                (
              
              公司
              
                )
              
                139
              
              
                0.
              
              organizationName_default      
              
                =
              
               beijing www company

              
                140
              
              
                145
              
               organizationalUnitName          
              
                =
              
              Organizational Unit 
              
                Name
              
              
                (
              
              eg
              
                ,
              
              section
              
                )
              
              ##
              
                组织单元
              
              
                (
              
              部门
              
                )
              
                146
              
               organizationalUnitName_default  
              
                =
              
               www

              
                147
              
              
                148
              
               commonName                      
              
                =
              
               Common 
              
                Name
              
              
                (
              
              e
              
                .
              
              g
              
                .
              
              server 
              
                FQDN
              
               or 
              
                YOUR
              
               name
              
                )
              
              ##服务器域名

              
                149
              
               commonName                      
              
                =
              
               www
              
                .
              
              baidu
              
                .
              
              com

              
                150
              
               commonName_max                  
              
                =
              
              
                64
              
              
                151
              
              
                152
              
               #emailAddress                  
              
                =
              
               Email Address      ##Email地址

              
                153
              
               emailAddress                    
              
                =
              
               admin@baidu
              
                .
              
              com

              
                154
              
               emailAddress_max                
              
                =
              
              
                64
              
              
                155
              
              
                156
              
               # 
              
                SET
              
              
                -
              
              ex3                      
              
                =
              
              
                SET
              
               extension number 
              
                3
              
              
                157
              
              
                158
              
              
                [
              
               req_attributes 
              
                ]
              
              
                159
              
               #challengePassword              
              
                =
              
              
                A
              
               challenge password  ##修改密码

              
                160
              
               challengePassword              
              
                =
              
              
                161
              
              
                163
              
               challengePassword_min          
              
                =
              
              
                4
              
              
                164
              
               challengePassword_max          
              
                =
              
              
                20
              
            
          

二、 安装Tornado

Tornado是目前python一个非常留下的非阻塞式服务器框架
若想了解更多,请参考 官方文档(中文版)

安装命令:

            
              
                sudo
              
               pip 
              
                install
              
               tornado

            
          

Tornado 本身支持 SSL ,所以我们这里需要做的主要是生成可用的证书。

三、生成证书

生成SSL证书

首先要生成服务器端的私钥(key文件)

            
              $ openssl genrsa -des3 -out server.key 1024

            
          

生成CSR文件

将之前的openssl.cnf 拷贝到所需目录中

            
              $ openssl req -new -key server.key -out server.csr -config openssl.cnf

            
          

生成Certificate Signing Request(CSR),生成的csr文件交给CA签名后形成服务端自己的证书.屏幕上将有提示,依照其指示一步一步输入要求的个人信息即可.

对客户端也作同样的命令生成key及csr文件:

            
              $ openssl genrsa -des3 -out client.key 1024
$ openssl req -new -key client.key -out client.csr -config openssl.cnf

            
          

CSR文件必须有CA的签名才可形成证书.可将此文件发送到verisign等地方由它验证,要交一大笔钱,何不自己做CA呢.
在bin目录下新建目录 demoCA、demoCA/certs、demoCA/newcerts
在demoCA建立一个空文件 index.txt
在demoCA建立一个文本文件 serial, 没有扩展名,内容是一个合法的16进制数字,例如 0000

这里说明一下,在我的目录下 /etc/pki/CA/ 已经存在了这些certs文件夹,所以只需要在这个文件下新建index.txt, serial即可

            
              openssl req 
              
                -
              
              
                new
              
              
                -
              
              x509 
              
                -
              
              keyout ca
              
                .
              
              key 
              
                -
              
              out ca
              
                .
              
              crt 
              
                -
              
              config openssl
              
                .
              
              cnf

            
          

用生成的CA的证书为刚才生成的server.csr,client.csr文件签名:

            
              $ openssl ca 
              
                -
              
              
                in
              
               server
              
                .
              
              csr 
              
                -
              
              out server
              
                .
              
              crt 
              
                -
              
              cert ca
              
                .
              
              crt 
              
                -
              
              keyfile ca
              
                .
              
              key 
              
                -
              
              config openssl
              
                .
              
              cnf
$ openssl ca 
              
                -
              
              
                in
              
               client
              
                .
              
              csr 
              
                -
              
              out client
              
                .
              
              crt 
              
                -
              
              cert ca
              
                .
              
              crt 
              
                -
              
              keyfile ca
              
                .
              
              key 
              
                -
              
              config openssl
              
                .
              
              cnf

            
          

ok,到了这里应该已经创建了可以使用的证书了,如果在为文件签名的时候有错误,那多半是信息不正确,这时可以去清空一下 index.txt 里的信息,然后重新执行第5步里失败的操作。

在Tornado网站中开启HTTPS

接着可以测试一下 tornado 使用 ssl 的证书了。
写个测试项目,其实也就一个py文件,像:

            
              
                import
              
               os
              
                .
              
              path


              
                from
              
               tornado 
              
                import
              
               httpserver

              
                from
              
               tornado 
              
                import
              
               ioloop

              
                from
              
               tornado 
              
                import
              
               web


              
                class
              
              
                TestHandler
              
              
                (
              
              web
              
                .
              
              RequestHandler
              
                )
              
              
                :
              
              
                def
              
              
                get
              
              
                (
              
              self
              
                )
              
              
                :
              
              
        self
              
                .
              
              write
              
                (
              
              
                "Hello, World!"
              
              
                )
              
              
                def
              
              
                main
              
              
                (
              
              
                )
              
              
                :
              
              
    settings 
              
                =
              
              
                {
              
              
                "static_path"
              
              
                :
              
               os
              
                .
              
              path
              
                .
              
              join
              
                (
              
              os
              
                .
              
              path
              
                .
              
              dirname
              
                (
              
              __file__
              
                )
              
              
                ,
              
              
                "static"
              
              
                )
              
              
                ,
              
              
                }
              
              
    application 
              
                =
              
               web
              
                .
              
              Application
              
                (
              
              
                [
              
              
                (
              
              r
              
                "/"
              
              
                ,
              
               TestHandler
              
                )
              
              
                ,
              
              
                ]
              
              
                ,
              
              
                **
              
              settings
              
                )
              
              
    server 
              
                =
              
               httpserver
              
                .
              
              HTTPServer
              
                (
              
              application
              
                ,
              
               ssl_options
              
                =
              
              
                {
              
              
                "certfile"
              
              
                :
              
               os
              
                .
              
              path
              
                .
              
              join
              
                (
              
              os
              
                .
              
              path
              
                .
              
              abspath
              
                (
              
              
                "."
              
              
                )
              
              
                ,
              
              
                "server.crt"
              
              
                )
              
              
                ,
              
              
                "keyfile"
              
              
                :
              
               os
              
                .
              
              path
              
                .
              
              join
              
                (
              
              os
              
                .
              
              path
              
                .
              
              abspath
              
                (
              
              
                "."
              
              
                )
              
              
                ,
              
              
                "server.key"
              
              
                )
              
              
                ,
              
              
                #我的代码是吧.改成了/home/SSLCertificate,其他不变
              
              
                }
              
              
                )
              
              
    server
              
                .
              
              listen
              
                (
              
              
                8000
              
              
                )
              
              
    ioloop
              
                .
              
              IOLoop
              
                .
              
              instance
              
                (
              
              
                )
              
              
                .
              
              start
              
                (
              
              
                )
              
              
                if
              
               __name__ 
              
                ==
              
              
                "__main__"
              
              
                :
              
              
    main
              
                (
              
              
                )
              
            
          

然后把相关的证书扔到 py 文件的目录下。改成相应的名字。然后开启服务。
接着用使用 curl

            
              curl 
              
                -
              
              k https
              
                :
              
              
                /
              
              
                /
              
              localhost
              
                :
              
              
                8000
              
            
          

-k 是跳过验证

看到请求返回的 Hello, World! 了么?恭喜你~你成功了~


至于后面务端会出现服 Enter PEM pass phrase ,请参考我的另外一篇博客解决服务器每次都要输入Enter PEM pass phrase

参考:

http://www.yeolar.com/note/2015/04/30/tornado-ssl-https/
https://www.jianshu.com/p/5880ae1cd595


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请请扫描上面二维码支持博主1元、2元、5元等您想捐的金额吧,狠狠点击下面给点支持吧

发表我的评论
最新评论 总共0条评论