day31:socketserver&hashlib&hmac&TCP登
目录1.socketserver:实现TCP协议下Server端的并发 2.hashlib模块 3.hashlib应用:文件校验 4.hmac应用:服务器的合法性校验 5.TCP登录程序 1.socketserver:实现TCP协议下Server端的并发1.socketserver的基本语法服务端 # ### 服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): print("handle方法被执行了") ThreadingTCPServer(ip端口号,自定义的类) server = socketserver.ThreadingTCPServer( (127.0.0.1",9000),MyServer ) 建立连接,循环调用 server.serve_forever() 客户端 ### 客户端 socket sk = socket.socket() sk.connect( () ) 处理收发数据的逻辑 sk.close() 2.socketserver实现server端的并发服务端 handle(self): conn = self.request self.request就是我们之前熟悉的conn对象 while True: 接受数据 msg = conn.recv(1024) msg2 = msg.decode(utf-8) print(msg2) conn.send(msg2.upper().encode()) ) ) True: sk.send(byou can you up no can no bb) msg = sk.recv(1024) print(msg.decode()) sk.close() 3.关于sockerserver,你需要注意:.1.在server端定义MyServer类,继承BaseRequestHandler类 2.收发数据的逻辑都写在MyServer类下的handler方法中,注意!函数名只能为handle,不可以乱起函数名 3.定义完类,要做两件事 server = socketserver.ThreadingTCPServer( ("127.0.0.1",9000),MyServer ) server.serve_forever() 2.hashlib模块1.基本用法基本用法 # 1.创建一个md5算法的对象 hm = hashlib.md5() 2.把要加密的字符串通过update更新到hm这个对象中运算 hm.update(123456".encode(")) 里面的数据必须是二进制字节流 3.获取32位16进制字符串 res = hm.hexdigest() 2.味道不够?加盐!!什么是加盐??加盐(加key => Xboy_) 加一个关键字配合原字符进行加密,是密码更复杂,不容易被破解 加盐(加key => Xboy_) 加一个关键字配合原字符进行加密,不容易被破解 hm = hashlib.md5(Xboy_wangwen.encode()) hm.update(.encode()) res = hm.hexdigest() print(res,len(res)) 3.进阶版:动态加盐通过引入随机数模块,每次都生成一个不同的数字和密码进行加密 动态加盐 num = str(random.randrange(100000,1000000)) hm = hashlib.md5(num.encode()) hm.update(.encode()) res = hm.hexdigest() 4.除了常见的md5加密,还有sha加密sha和md5的不同之处: sha 算出来的十六进制的串是40位,加密稍慢,安全性稍高 md5 算出来的十六进制的串是32位,加密很快,安全性稍差 sha1版本 hs = hashlib.sha1() hs.update(我最是牛逼的&#*($&*(#&%*(&%*&%(#%& hs.hexdigest() 31673dd65f81fddaae07b4240cbb04af047b7496 sha512版本 hs = hashlib.sha512() hs.update(hmac hmac.new(盐,密码) key = ba msg = b hn = hmac.new(key,msg) res = hn.hexdigest() 32位长度 十六进制的字符串 2.动态加盐 在加盐前,我们需要了解一个知识:通过os.urandom 可以返回随机的二进制字节流 key = os.urandom(32) msg = b123(1) 针对于小文件进行内容校验 check_md5(filename): hs = hashlib.md5() 创建md5加密对象 with open(filename,mode=rb") as fp: 打开文件 hs.update(fp.read()) 将读出的内容(字符串)通过update更新到hs对象中进行加密运算 return hs.hexdigest() 返回加密后的16进制字符串 res1 = check_md5(ceshi1.txt) res2 = check_md5(ceshi2.txt) print(res1,res2) 2.针对于大文件进行内容校验针对于大文件进行内容校验,我们可以通过update 把字符串分段进行加密 常规方法 strvar = 今天是星期五,好开心了,下周一又要考试了. hm = hashlib.md5() hm.update(strvar.encode()) res =(res) 分段更新加密 hm = hashlib.md5() hm.update(下周一又要考试了.print(res) 通过运行我们可以发现两个res的值是相同的,说明了大文件分段加密是可行的 ? 3.用文件操作对大文件进行分段加密?方法一 方法一 先弄个md5的加密对象 with open(filename,1)"> 打开文件 True: content = fp.read(10) 一次最多读取10个字节 if content: 读取到了内容:代表文件里还有东西 分批进行字符串密码更新 hs.update(content) else: 读取不到内容:代表文件已经全读取完了,可以结束了 break return hs.hexdigest() res1 = check_md5(check_md5(filename): hs = hashlib.md5() 计算文件大小=>返回字节数 filesize = os.path.getsize(filename) 先获取到文件的大小 with open(filename,1)">whilefilesize: 当文件大小不为0时 content = fp.read(10) 一次最多读取10个字节 hs.update(content) 读一点更新一点 按照实际的字节个数读取 filesize -= len(content) hs.hexdigest() res1 = check_md5(auth(conn,secret_key): 随机产生32位的二进制字节流 msg = os.urandom(32) conn.send(msg) hn = hmac.new(secret_key.encode(),msg) res_server = hn.hexdigest() print(res_server) 461ea12ca8ef475caeedd0c742f4295e 服务端接受客户端发送过来的数据进行验证; res_client = conn.recv(1024).decode() if res_client == res_server: 你是合法的服务端用户) True else: 不是合法的服务端用户 False sk = socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind( () ) sk.listen() 三次握手 conn,addr = sk.accept() 处理收发数据的逻辑 secret_key = 芝麻开门 res = 在验证成功之后,给客户端发送状态码 if res: conn.send(状态码是200:付款成功~.encode()) 四次挥手 conn.close() 退还端口 sk.close() 客户端: auth(sk,1)"> 处理收发数据的逻辑 msg = sk.recv(32) hn = hn.hexdigest() 把客户端加密的字符串发送给服务端进行验证 sk.send(res.encode()) sk =芝麻开门123 auth(sk,接受服务端给我的验证码 res = sk.recv(1025).decode((res) sk.close() 5.TCP登录程序服务端: get_md5_code(usr,pwd): hs = hashlib.md5(usr.encode()) hs.update(pwd.encode()) hs.hexdigest() res = get_md5_code("tianqi","777") print(res) sk = socket.socket() sk.bind( () ) sk.listen() conn,addr = sk.accept() 处理收发数据的逻辑 msg = conn.recv(1024).decode() 把反解之后的字符串恢复原来的数据格式变成字典通过json dic = json.loads(msg) (dic) sign = False with open(userinfo.txtr) as fp: for line in fp: usr,pwd = line.strip().split(: print(usr,pwd) if usr == dic[username"] and pwd == get_md5_code(dic["],dic[password]): 制定状态码 0=>失败 1=>成功 res = {code":1} res_msg = json.dumps(res).encode() conn.send(res_msg) sign = True break if sign == False: 发送错误的状态码 res = {:0} res_msg = json.dumps(res).encode() conn.send(res_msg) 客户端: sk = 处理收发数据的逻辑 usr = input(请输入您的用户名:) pwd = input(请输入您的密码:) dic = {":usr,":pwd,1)">operate":login} 先通过json变成字符串 res = json.dumps(dic) json字符串 -> 字节流 bytes_msg = res.encode() 把字节流发送给服务端 sk.send(bytes_msg) 接受服务端发送过来的数据 res_msg = sk.recv(1024).decode() dic_code = json.loads(res_msg) if dic_code[]: 恭喜你~ 登录成功: i am so sorry ~ 登录失败) sk.close() ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |