若是你想在分佈式系統中實現一個簡單的客戶端連接認證功能,又不像SSL那麼複雜,那麼利用hmac+加鹽的方式來實現。python
客戶端驗證的總的思路是將服務端隨機產生的指定位數的字節發送到客戶端,兩邊同時用hmac進行加密,而後對生成的密文進行比較,相同就是合法的客戶端,不相同就是不合法的端戶端。服務器
dom
服務端socket
from socket import * import hmac, os secret_key = b"nick" # 是指一個固定字符串的key def conn_auth(conn): # 定義函數認證客戶端鏈接 print('開始驗證新連接的合法性') # 打印提示 msg = os.urandom(32) # 隨機生成一個32位的數 conn.sendall(msg) # 鏈接發送這個隨機的數 h = hmac.new(secret_key, msg) # 傳入要生成hmac摘要值的信息 digest = h.digest() # 生成一個hmac摘要 respone = conn.recv(len(digest)) # 接收回應,鏈接接收一個服務器端摘要的長度的信息 return hmac.compare_digest(respone, digest) # 比較客戶端和服務端計算的摘要結果,同樣則是True,不同則是False def data_handler(conn, bufsize=1024): # 數據處理機函數(傳入兩個參數conn,和設置的默認大小) if not conn_auth(conn): # 若是沒有連接 print('該連接不合法,關閉') # 打印該連接不合法,關閉 conn.close() # 關閉連接 return print('連接合法,開始通訊') # 連接合法,開始通訊 while True: # 循環爲真 data = conn.recv(bufsize) # 接收數據 if not data: break # 若是沒有數據則打斷 conn.sendall(data.upper()) # 連接發送數據 def server_handler(ip_port, bufsize, backlog=5): # 服務器處理機ip和端口,設置大小 ''' 只處理連接 :param ip_port: :return: ''' tcp_socket_server = socket(AF_INET, SOCK_STREAM) # 實例化一個tcp的套接字 tcp_socket_server.bind(ip_port) # 綁定ip端口 tcp_socket_server.listen(backlog) # 監聽 while True: # 循環爲真 conn, addr = tcp_socket_server.accept() # 接收連接和地址 print('新鏈接[%s:%s]' % (addr[0], addr[1])) # 打印新鏈接ip和端口 data_handler(conn, bufsize) # 調用數據處理機函數 if __name__ == '__main__': ip_port = ('127.0.0.1', 9999) bufsize = 1024 server_handler(ip_port, bufsize)
客戶端tcp
from socket import * import hmac, os secret_key = b'nick' # 設置一個字符串key def conn_auth(conn): # 定義一個客戶驗證到服務器端的連接 ''' 驗證客戶端到服務器的連接 :param conn: :return: ''' msg = conn.recv(32) # 接受一個32位的信息 h = hmac.new(secret_key, msg) digest = h.digest() # 獲得一個摘要值 conn.sendall(digest) # 發送這個摘要 def client_handler(ip_port, bufsize=1024): tcp_socket_client = socket(AF_INET, SOCK_STREAM) # 建立一個tcp套接字的對象 tcp_socket_client.connect(ip_port) conn_auth(tcp_socket_client) # 執行驗證 while True: data = input('>>: ').strip() # 輸入內容 if not data: continue # 若是沒有內容則跳過 if data == 'quit': break tcp_socket_client.sendall(data.encode('utf-8')) # 發送數據 respone = tcp_socket_client.recv(bufsize) # 接收數據 print(respone.decode('utf-8')) # 打印接收的數據 tcp_socket_client.close() # 關閉這個套接字 if __name__ == '__main__': ip_port = ('127.0.0.1', 9999) bufsize = 1024 client_handler(ip_port, bufsize)