zoukankan      html  css  js  c++  java
  • 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()

    客户端

    # ### 客户端
    import socket
    sk = socket.socket()
    sk.connect( ("127.0.0.1",9000) )
    
    # 处理收发数据的逻辑
    
    sk.close()

    2.socketserver实现server端的并发

    服务端

    # ### 服务端
    import socketserver
    
    class MyServer(socketserver.BaseRequestHandler):
        def 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())
                    
    # ThreadingTCPServer(ip端口号,自定义的类)
    server = socketserver.ThreadingTCPServer( ("127.0.0.1",9000) , MyServer )
    # 建立连接,循环调用
    server.serve_forever()

    客户端

    # ### 客户端
    import socket
    sk = socket.socket()
    sk.connect( ("127.0.0.1",9000) )
    # 处理收发数据的逻辑
    while True:
        sk.send(b"you can you up no can no bb")
    
        msg = sk.recv(1024)
        print(msg.decode("utf-8"))
    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("utf-8")) # 里面的数据必须是二进制字节流
    # 3.获取32位16进制字符串
    res = hm.hexdigest() 

    2.味道不够?加盐!!

    什么是加盐? 加盐(加key => Xboy_) 加一个关键字配合原字符进行加密,是密码更复杂,不容易被破解

    # 加盐(加key => Xboy_) 加一个关键字配合原字符进行加密,是密码更复杂,不容易被破解
    hm = hashlib.md5("Xboy_wangwen".encode())
    hm.update("123456".encode())
    res = hm.hexdigest()
    print(res , len(res))

    3.进阶版:动态加盐

    通过引入随机数模块,每次都生成一个不同的数字和密码进行加密

    # 动态加盐
    num = str(random.randrange(100000,1000000))
    hm = hashlib.md5(num.encode("utf-8"))
    hm.update("123456".encode())
    res = hm.hexdigest()

    4.除了常见的md5加密,还有sha加密

    sha和md5的不同之处:

    sha 算出来的十六进制的串是40位,加密稍慢,安全性稍高

    md5 算出来的十六进制的串是32位,加密很快,安全性稍差

    # sha1版本
    hs = hashlib.sha1()
    hs.update("我最是牛逼的&#*($&*(#&%*(&%*&%(#%&".encode())
    res = hs.hexdigest()
    print(res, len(res)) # 31673dd65f81fddaae07b4240cbb04af047b7496
    
    # sha512版本
    hs = hashlib.sha512()
    hs.update("123456".encode())
    res = hs.hexdigest()
    print(res , len(res))

    5.还有更牛逼的hmac加密

    hmac加密的优势:hmac 加密算法更加复杂,不容易破解

    1.基本语法

    import hmac
    # hmac.new(盐,密码)
    key = b"a"
    msg = b"123456"
    hn = hmac.new(key,msg)
    res = hn.hexdigest()
    print(res, len(res)) # 32位长度 十六进制的字符串

    2.动态加盐

    在加盐前,我们需要了解一个知识:通过os.urandom 可以返回随机的二进制字节流

    key = os.urandom(32)
    msg = b"123"
    hn = hmac.new(key,msg)
    res = hn.hexdigest()
    print(res, len(res))

    3.hashlib应用:文件校验

    1.针对于小文件进行内容校验

    # (1) 针对于小文件进行内容校验
    def 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 = hm.hexdigest()
    print(res)
    
    # 分段更新加密
    hm = hashlib.md5()
    hm.update("今天是星期五,好开心了,".encode())
    hm.update("下周一又要考试了.".encode())
    res = hm.hexdigest()
    print(res)

    通过运行我们可以发现两个res的值是相同的,说明了大文件分段加密是可行的

    3.用文件操作对大文件进行分段加密 

    方法一

    # 方法一
    def check_md5(filename):
        hs = hashlib.md5() # 先弄个md5的加密对象
        with open(filename,mode="rb") as fp: # 打开文件
            while True:
                content = fp.read(10) # 一次最多读取10个字节
                if content: # 读取到了内容:代表文件里还有东西
                    # 分批进行字符串密码更新
                    hs.update(content)
                else: # 读取不到内容:代表文件已经全读取完了,可以结束了
                    break
    
            return hs.hexdigest()
    
        
    res1 = check_md5("ceshi1.txt")
    res2 = check_md5("ceshi2.txt")
    print(res1,res2)

    方法二

    def check_md5(filename):
        hs = hashlib.md5()
        # 计算文件大小=>返回字节数
        filesize = os.path.getsize(filename) # 先获取到文件的大小
        with open(filename,mode="rb") as fp: # 打开文件
            while filesize: # 当文件大小不为0时            
                content = fp.read(10) # 一次最多读取10个字节
                hs.update(content) # 读一点更新一点
                # 按照实际的字节个数读取
                filesize -= len(content)
                
            return hs.hexdigest()
    
    res1 = check_md5("ceshi1.txt")
    res2 = check_md5("ceshi2.txt")
    print(res1,res2)

    4.hmac应用:服务器的合法性校验

    服务端:

    def 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("utf-8")
            
        if res_client == res_server:
            print("你是合法的服务端用户")
            return True
        else:
            print("不是合法的服务端用户")
            return False
    
    
    sk = socket.socket()
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    sk.bind( ("127.0.0.1",9000) )
    sk.listen()
    
    # 三次握手
    conn,addr = sk.accept()
    
    # 处理收发数据的逻辑
    secret_key = "芝麻开门"
    res = auth(conn,secret_key)
    
    # 在验证成功之后,给客户端发送状态码
    if res:
        conn.send("状态码是200:付款成功~".encode())
    # 四次挥手
    conn.close()
    # 退还端口
    sk.close()

    客户端:

    def auth(sk,secret_key):
        # 处理收发数据的逻辑
        msg = sk.recv(32)
        hn = hmac.new(secret_key.encode(),msg)
        res = hn.hexdigest()
        
        # 把客户端加密的字符串发送给服务端进行验证
        sk.send(res.encode("utf-8"))
    
    
    sk = socket.socket()
    sk.connect( ("127.0.0.1",9000) )
    
    # 处理收发数据的逻辑
    secret_key = "芝麻开门123"
    auth(sk,secret_key)
    
    # 在验证成功之后,接受服务端给我的验证码
    res = sk.recv(1025).decode("utf-8")
    print(res)
    
    sk.close()

    5.TCP登录程序

    服务端:

    def get_md5_code(usr,pwd):
        hs = hashlib.md5(usr.encode())
        hs.update(pwd.encode())
        return hs.hexdigest()
    
    # res = get_md5_code("tianqi","777")
    # print(res)
    
    sk = socket.socket()
    sk.bind( ("127.0.0.1", 9001) )
    sk.listen()
    conn,addr = sk.accept()
    
    
    # 处理收发数据的逻辑
    msg = conn.recv(1024).decode()
    # 把反解之后的字符串恢复原来的数据格式变成字典通过json
    dic = json.loads(msg)
    print(dic)
    
    sign = False
    with open("userinfo.txt",mode="r",encoding="utf-8") as fp:
        for line in fp:
            usr,pwd = line.strip().split(":")
            # print(usr,pwd)
            if usr == dic["username"] and pwd == get_md5_code(dic["username"],dic["password"]):
                # 制定状态码 0=>失败 1=>成功
                res = {"code":1}
                res_msg = json.dumps(res).encode()
                conn.send(res_msg)
                sign = True
                break
    
    if sign == False:
        # 发送错误的状态码
        res = {"code":0}
        res_msg = json.dumps(res).encode()
        conn.send(res_msg)
        

    客户端:

    sk = socket.socket()
    sk.connect( ("127.0.0.1", 9001) )
    
    # 处理收发数据的逻辑
    usr = input("请输入您的用户名:")
    pwd = input("请输入您的密码:")
    dic = {"username":usr,"password":pwd,"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["code"]:
        print("恭喜你~ 登录成功")
    else:
        print("i am so sorry ~ 登录失败")
    
    sk.close()
  • 相关阅读:
    DP实验
    Linux shell学习
    线性排序算法-计数排序
    算法笔试题练习
    堆排序
    node.js初识
    linux下vim命令详解
    html5学习笔记
    有趣的参数收集
    算法学习-归并排序
  • 原文地址:https://www.cnblogs.com/libolun/p/13504198.html
Copyright © 2011-2022 走看看