2013-12-09 103 views
4

我寫了一個簡單的網絡服務器&客戶端與Python,以下是我的代碼。我想實現HTTPS,因爲我使用的是標準SSL庫。我正在使用Python 2.7.3。我生成了證書文件並自行簽名。所以我有.crt和.key文件,我用它來綁定套接字。HTTPS服務器與Python

當我從瀏覽器中瀏覽它時,出現證書自簽名的異常錯誤,我必須將其添加到例外。然後它工作。

代碼我的服務器的:

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

將您的certfile與請求提供的文件進行比較,確保它們都是相同的格式。這是最明顯的失敗原因。 – Lukasa

+0

他們是一樣的。事實上,我從同一個文件夾運行客戶端和服務器,他們使用相同的密鑰 – avi

+0

這不是我的意思。請求提供一個默認的'cacert.pem'文件,你可以在這裏看到(https://github.com/kennethreitz/requests/blob/master/requests/cacert.pem)。我的意思是你應該確保這裏的格式與你的certfile的格式相匹配。 – Lukasa

回答

4

SSL證書只有在客戶端具有用於簽署驗證證書的證書時才能進行驗證。 這是自簽名證書在互聯網上不常用的主要原因。 通常你會要求一些組織(證書頒發機構)用它的簽名證書。 這些CA通常由人員和其他組織信任,以便他們的證書已經內置在許多客戶端中。

所以,如果你想讓每個人都能夠驗證你的證書,你不應該自我簽名。那裏有很多CA,其中一些可以免費頒發證書。 除非您獲得CA簽名證書,否則只有已經擁有證書的人員纔會對其進行驗證。

編輯:

作爲一個邊注:當你告訴你的瀏覽器添加一個例外你告訴他在其所有的證書無法驗證一個特定的網站。所以你不會受到MITM的保護。

+0

我不希望每個人都能夠驗證我的證書。我知道的只有很少的人。 – avi

+0

在這種情況下,您可以使用自簽名證書,但必須將其提供給需要連接到服務器的所有人。 然後他們應該在瀏覽器中添加它。相反,如果他們添加一個異常,SSL的使用就變得毫無意義。 – smeso

+0

是的,我可以把它給人。 – avi