我写过一个简单的网络服务器&客户端使用python,以下是我的代码。我想实现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)
但是我尝试使用请求模块,当我向.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]>
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)
那么这是否意味着只有拥有我的证书文件(my_cert.crt)的人才能发送请求并得到回复,而那些不能回复的人将无法做到?
答案 0 :(得分:4)
只有具有用于签署验证证书的证书的客户端才能验证SSL证书。 这是自签名证书在Internet上不常用的主要原因。 通常,您会要求某个组织(证书颁发机构)使用其签署证书。 这些CA通常受到人员和其他组织的信任,因此他们的证书已经内置于许多客户端中。
因此,如果您想让每个人都能够验证您的证书,那么您就不应该对其进行自我签名。那里有很多CA,其中一些免费发放证书。 除非您获得CA签名证书,否则只有已拥有证书的人才会对其进行验证。
编辑:
作为旁注:当您告诉浏览器为特定网站添加例外时,您告诉他不要验证其所有证书。所以你不会受到MITM的保护。