• 验证客户端的链接合法性


    什么是验证合法性?

    即在客户端想要和客户端进行链接的时候, 我们对客户端的身份进行验证是否合法. 

    我们如果想在分布式系统中实现一个简单的客户端链接认证功能, 但是又不想SSL那么复杂, 那么我们可以利用hmac + 加盐的方式来实现.

    首先介绍两个方法,:

    1. os.urandom(n)

    该方法是一种bytes类型的随机生成n个字节字符串的方法, 而且每次生成的值都不相同.

    import hmac
    message = b'Hello world'
    key = b'secret'
    h = hmac.new(key,message,digestmod='MD5')
    print(h.hexdigest())
    #比较两个密文是否相同,可以用hmac.compare_digest(密文、密文),然会True或者False。
    os.urandom用法示例

     2.hmac:

    我们之前了解了用hashlib进行MD5加密. 该方法其实和它差不多.

    python自带的hmac模块实现了标准的Hmac算法, 我们首先需要准备待计算的原始消息message,随机key和哈希算法, 这里采用MD5算法.

    具体使用方法如下:

    import hmac
    message = b'Hello world'
    key = b'secret'
    h = hmac.new(key,message,digestmod='MD5')
    print(h.hexdigest())
    #比较两个密文是否相同,可以用hmac.compare_digest(密文、密文),然会True或者False。
    hmac用法示例

     hmac输出的长度和原始哈希算法的长度一致。需要注意传入的key和message都是bytes类型,str类型需要首先编码为bytes

    下面是利用hmac+加盐的方式来实现一个简单的客户端链接认证功能的例子:

    from socket import *
    import hmac, os
    
    secret_key = b"hello, world!"
    
    def conn_auth(conn):
        """
        认证客户端链接
        :param conn:
        :return: 验证结果
        """
        print("开始验证新连接的合法性")
        msg=os.urandom(32)  # 生成一个32字节的随机字符串
        conn.sendall(msg)
        h = hmac.new(secret_key, msg)   # 生成密文
        digest = h.digest()
        respone = conn.recv(len(digest))
        return hmac.compare_digest(digest, respone) # 返回结果True或者False
    
    def data_handler(conn, bufsize=1024):
        """
        根据验证结果, 判断是否通信
        :param conn:
        :param bufsize:
        :return:
        """
        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):
        """
        只处理链接
        :param ip_port:
        :param bufsize:
        :param backlog:
        :return:
        """
        tcp_socket_server=socket(AF_INET, SOCK_STREAM)
        tcp_socket_server.bind(ip_port)
        tcp_socket_server.listen(backlog)
        while 1:
            conn, addr = tcp_socket_server.accept()
            print("新连接[%s, %s]" %(addr[0],addr[1]))
            data_handler(conn, bufsize)
    
    
    if __name__ == '__main__':
        ip_port = ("127.0.0.1", 8808)
        bufsize = 1024
        server_handler(ip_port, bufsize)
    验证合法性链接_服务端
    from socket import *
    import hmac, os
    
    secret_key = b"hello, world!"
    
    def conn_auth(conn):
        """
        接收服务端的随机码, 加密后发给服务端
        :param conn:
        :return:
        """
        msg = conn.recv(32)
        h = hmac.new(secret_key, msg)
        digest = h.digest()
        conn.sendall(digest)
    
    
    def client_handler(ip_port, bufsize):
        """
        创建TCP下的socket, 与服务端通信
        :param ip_port:
        :param bufsize:
        :return:
        """
        tcp_socket_client = socket(AF_INET, SOCK_STREAM)
        tcp_socket_client.connect(ip_port)
        conn_auth(tcp_socket_client)
    
        while 1:
            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"))
    
    if __name__ == '__main__':
        ip_port = ("127.0.0.1", 8808)
        bufsize = 1024
        client_handler(ip_port, bufsize)
    验证合法性链接_客户端
  • 相关阅读:
    开发中遇到的问题点
    ThreadLocal
    Java多线程10:join()方法
    Java多线程9:中断机制
    Java多线程8:wait()和notify()/notifyAll()
    Java多线程7:死锁
    Java多线程0:核心理论
    MySQL中and和or的优先级的问题
    Java多线程6:Synchronized锁代码块(this和任意对象)
    shiro英语
  • 原文地址:https://www.cnblogs.com/af1y/p/10023347.html
Copyright © 2020-2023  润新知