带有Python的HTTPS服务器

avi*_*avi 6 python ssl webserver python-requests

我已经用python编写了一个简单的Web服务器和客户端,以下是我的代码。我要实现HTTPS,因为我正在使用标准SSL库。我正在使用Python 2.7.3。我生成了证书文件并对其进行了自签名。所以我有.crt和.key文件,可以用它们来绑定套接字。

当我从浏览器中浏览证书时,出现异常错误,即证书是自签名的,必须将其添加到异常中。然后就可以了。

我的服务器代码:

import BaseHTTPServer
import urlparse
import urllib 
import SocketServer
import threading
import ssl

HOST_NAME = 'localhost'
PORT_NUMBER = 8089


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_GET(self):

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        if self.path == '/get/':
            self.wfile.write('On /get/')
            return
        self.wfile.write('On root')
        return    

    def do_POST(self):
        pass

class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
    pass


if __name__ == '__main__':
    httpd = BaseHTTPServer.HTTPServer((HOST_NAME, PORT_NUMBER), Handler)
    httpd.socket = ssl.wrap_socket (httpd.socket, keyfile='my_key.key', certfile='my_cert.crt', server_side=True)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        httpd.server_close()
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER)
Run Code Online (Sandbox Code Playgroud)

但是,我试图使用请求模块,当我向.crt文件提供请求时,出现以下错误:

requests.get('https://localhost:8089', verify=True)
#requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

requests.get('https://localhost:8089', verify='my_cert.crt')
#requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

requests.get('https://localhost:8089', cert='my_crt.crt')
#requests.exceptions.SSLError: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

requests.get('https://localhost:8089', cert=('my_crt.crt', 'my_key.key'))
# requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed    

requests.get('https://localhost:8089', verify=False)
#<Response [200]>
Run Code Online (Sandbox Code Playgroud)

1)为什么我会收到此错误?我当然不想使用'verify = False'。我想在客户端验证证书。

2)(假设我可以使它工作)如果我通过更改来强制执行cert_reqs = CERT_REQUIRED:

httpd.socket = ssl.wrap_socket (httpd.socket, keyfile='my_key.key', certfile='my_cert.crt', cert_reqs=CERT_REQUIRED, server_side=True)
Run Code Online (Sandbox Code Playgroud)

那么这是否意味着只有拥有我的证书文件(my_cert.crt)的人才可以发送请求并获得响应,而没有我的人则不能?

sme*_*eso 5

仅当客户端具有用于签署验证证书的证书时,才能验证 SSL 证书。这就是自签名证书在互联网上不常用的主要原因。通常您会要求某个组织(证书颁发机构)用其签署您的证书。这些 CA 通常受到人们和其他组织的信任,因此他们的证书已经内置在许多客户端中。

因此,如果您想让每个人都能够验证您的证书,您不应该对其进行自签名。那里有很多 CA,其中一些免费颁发证书。除非您获得 CA 签名的证书,否则只有已经拥有您的证书的人才会验证它。

编辑:

附带说明:当您告诉浏览器为特定站点添加例外时,您就是在告诉他不要验证其所有证书。因此,您不会受到 MITM 的保护。