zoukankan      html  css  js  c++  java
  • Python学习日记(三十二) hmac检验客户端的合法性和socketsever模块

    Hmac模块

    其实这个模块类似hashlib模块,它能将一些重要的信息通过算法加密成密文,让信息更具有安全性。

    关于hmac加密算法的了解:它的全名是哈希运算消息认证码(Hash-based Message Authentication Code),HMAC利用hash算法,以一个消息M和一个秘钥K作为输入,生成一个定长的消息摘要作为输出。HMAC算法利用已有的hash函数,关键问题是如何使用秘钥。

    使用

    import hmac                     #这个模块和hashlib机制很相似
    h = hmac.new(b'key',b'msg')     #需要一个秘钥(bytes类型)和你想进行加密的bytes类型数据,前面为随机的key后面为一个消息
    print(h.digest())               #结果拿到一个密文 
                                    #b'x18xe3Tx8cYxad@xddx03x90{zxeexe7x1dg'

    检验客户端合法性

    如何确定这个客户端是该服务器的合法客户端呢?如果两边实现都讲好了他们的秘钥就可以利用hmac.compare_digest()方法去比较他们最后产生的密文到底是不是相同的,如果是那就是合法的就进行相应的操作,若不合法就直接关闭。

    这里介绍一个新的os模块方法urandom(32)

    import os
    print(os.urandom(32))   #随机生成32位的字节
                            #b'xe2x84:x93x82Q9xffx9ex7fx8ax97)[xedn
    xa8xf0vx8bxc0gxbdxe7xebx0exa4xf0x80x0cx16'

    利用这种'加盐'的方法我们就能让我们产生的秘钥具有不确定性,更加安全

    检验合法的结果:

    Sever:

    import socket
    import hmac
    from os import urandom
    secret_key = b'egg'                                         #秘钥
    sk = socket.socket()
    sk.bind(('127.0.0.1',8090))
    sk.listen()
    
    def check_conn(conn):
        constant = urandom(32)
        conn.send(constant)
        h = hmac.new(secret_key,constant)                        #拿到一个密文对象
        sever_digest = h.digest()
        client_digest = conn.recv(1024)
        return hmac.compare_digest(sever_digest,client_digest)
    
    conn,addr = sk.accept()
    
    res = check_conn(conn)
    if res:
        print('合法的客户端!')                                    #合法的客户端!
        #进行一系列操作
        #conn.close()
        pass
    else:
        print('不合法的客户端!')
        conn.close()
    sk.close()

    Client:

    import socket
    import hmac
    
    secret_key = b'egg'
    sk = socket.socket()
    sk.connect(('127.0.0.1',8090))
    msg = sk.recv(1024)
    
    h = hmac.new(secret_key,msg)
    client_digest = h.digest()
    sk.send(client_digest)
    
    sk.close()

    那如果这个客户端它并不知道服务端的秘钥或者不知道服务端用的是HMAC进行的加密,那么它的结果很有可能是错误,给我们返回错误的客户端!

    Socketsever模块

    socketsever模块它能够实现多个客户端之间的交互

    基本实现

    Sever:

    import socketserver
    class Mysever(socketserver.BaseRequestHandler):                                 #一般情况下带Base都是作为父类,Request即请求,Handler就是处理
        def handle(self):
            print(self.request.recv(1024).decode('utf-8'))                          #self.request相当于一个conn
    
    
    if __name__ == '__main__':
        sever = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Mysever)         #Thread线程
                                                                                    #在一个程序里正常情况下只会有一个线程
                                                                                    #一个线程就是调度CPU的最小单位
                                                                                    #引入线程的概念去实现并发的效果
        sever.serve_forever()                                                       #表示我永远启用一个服务

    Client:

    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    sk.send('hi'.encode('utf-8'))
    sk.close()

    Output:

    hi

    有socketsever的原因就是我想同时处理多个客户端找我下载的请求,那socketsever只是在底层的基础上做了一层封装,帮我们实现了并发效果,所以没有'clientsever'这个概念,客户端只需要正常启用就好

    实现多个客户端交互

    Sever:

    import socketserver
    class Mysever(socketserver.BaseRequestHandler):
        def handle(self):
            while True:
                msg = self.request.recv(1024).decode('utf-8')
                print(msg)
                info = input('<<<').encode('utf-8')
                self.request.send('Sever:'.encode('utf-8') + info)
    if __name__ == '__main__':
        sever = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Mysever)
        sever.serve_forever()

    Client1:

    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    while True:
        msg = input('<<<').encode('utf-8')
        sk.send('Client1:'.encode('utf-8') + msg)
        print(sk.recv(1024).decode('utf-8'))
    sk.close()

    Client2:

    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    while True:
        msg = input('<<<').encode('utf-8')
        sk.send('Client2:'.encode('utf-8') + msg)
        print(sk.recv(1024).decode('utf-8'))
    sk.close()

    Output:

     

     

  • 相关阅读:
    UML学习笔记2
    UML学习笔记1
    IOS 删除git中的submodules 以sourceTree为例
    进入MySql小黑框的方法
    v-cloak v-text v-html
    构建一个vue实例
    SQL server 查询某个值在那张表那个字段
    centos镜像下载
    win10系统升级后mysql找不到服务及数据消失问题
    Visual Studio 2017设置版权的方法
  • 原文地址:https://www.cnblogs.com/Fantac/p/11553581.html
Copyright © 2011-2022 走看看