发布时间:2018-05-08 20:18:39编辑:Run阅读(5166)
验证客户端链接的合法性
如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用md5+加盐或者hmac+加盐的方式来实现
原理图
为什么要随机字符串,是为了防止网络传输过程中,被截取。
md5的实现方法
server端代码
import os import socket import hashlib sk = socket.socket() secret_key = '今晚打老虎' sk.bind(('127.0.0.1', 9595)) sk.listen() while True: try: conn, addr = sk.accept() random_bytes = os.urandom(32) # 随机返回一个长度为32位的bytes类型的组合 conn.send(random_bytes) md5 = hashlib.md5(secret_key.encode('utf-8')) md5.update(random_bytes) ret = md5.hexdigest() msg = conn.recv(1024).decode('utf-8') if msg == ret:print('是合法的客户端') else:conn.close() finally: sk.close() break
client端代码
import socket import hashlib secret_key = '今晚打老虎' sk = socket.socket() sk.connect(('127.0.0.1', 9595)) urandom = sk.recv(1024) md5_obj = hashlib.md5(secret_key.encode('utf-8')) md5_obj.update(urandom) sk.send(md5_obj.hexdigest().encode('utf-8')) print('---------') sk.close()
先运行server,再运行client,执行结果为
是合法的客户端
hmac模块,专门用来做客户端合法性验证的(加密认证)
server端代码
import os import socket import hmac secret_key = '床前明月光'.encode('utf-8') sk = socket.socket() sk.bind(('127.0.0.1', 9595)) sk.listen() while True: try: conn, addr = sk.accept() # 建立连接 random_bytes = os.urandom(32) # 随机一个32长度的bytes类型组合 conn.send(random_bytes) obj = hmac.new(key=secret_key, msg=random_bytes) ret = obj.hexdigest() msg = conn.recv(1024).decode('utf-8') if msg == ret:print('是合法的客户端') else:conn.close() finally: sk.close() break
client端代码
import socket import hmac secret_key = '床前明月光'.encode('utf-8') sk = socket.socket() sk.connect(('127.0.0.1', 9595)) urandom = sk.recv(32) hmac_obj = hmac.new(key=secret_key, msg=urandom) sk.send(hmac_obj.hexdigest().encode('utf-8')) print('---------') sk.close()
先运行server,再运行client,执行结果为
是合法的客户端
socketserver
实现多个客户端,同时连接
socketserver端代码
import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): while True: print(self.request) # 这里不能使用input,否则卡住了 self.request.send(b'hello') # 跟所有的client打招呼 print(self.request.recv(1024)) # 接收客户端的信息 if __name__ == '__main__': socketserver.TCPServer.allow_reuse_address = True server = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), MyServer) server.serve_forever()
client端代码
import socket sk = socket.socket() sk.connect(('127.0.0.1', 9000)) while True: print(sk.recv(1024)) inp = input('>>>').encode('utf-8') sk.send(inp) sk.close()
先运行socketserver,在运行client,执行结果如下,发送一个消息,打印一次hello,可以同时开多个client执行
模拟下载进度条:
import sys import time def processBar(num, tital): rate = num / tital rate_num = int(rate*100) if rate_num == 100: r = '\r下载进度: {}%\n'.format(rate_num) else: r = '\r下载进度: {}%'.format(rate_num) sys.stdout.write(r) sys.stdout.flush for i in range(101): processBar(i, 100) # 需要传入下载进度和文件总大小 time.sleep(0.1) # 模拟下载延迟
执行结果
上一篇: python3-socket黏包现象
下一篇: python3--进程
47743
46233
37107
34625
29227
25883
24743
19861
19414
17906
5713°
6312°
5832°
5885°
6981°
5827°
5842°
6358°
6313°
7670°