验证客户端的链接合法性

一、os.urandom(n)

    获取一种bytes类型的随机生成的n个字节字符串的方法,每次生成的值都不相同。

二、hmac

    hmac模块实现了标准的Hmac算法,首先需要准备待计算的原始消息key,和随机生成的msg,哈希算法,采用MD5,使用hmac的代码如下:

import hmac

key = b"Hello World"
msg = b"secret"

h = hmac.new(key, msg, digestmod='MD5')
print(h.hexdigest())  # 8a315e3168dcd347b8bb3e2517da7b4d

注:传入的key和msg必须为bytes类型。

三、验证客户端的链接合法性

    如果服务端想限制客户端访问,就必须对客户端进行认证,认证通过方可访问。否则客户端只需知道服务端ip和端口号就能对其进行访问。

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

服务端:

import socket
import hmac
import os


secret_key = b"Jedan has a big key!"  #


def conn_auth(conn):
    """
    认证客户端链接
    :param conn:管道
    :return:True/False
    """
    print("开始验证新链接的合法")
    msg = os.urandom(32)  # 生成一个32字节的bytes类型随机字符串
    conn.sendall(msg)  # 发送随机字符串
    h = hmac.new(secret_key, msg)
    digest = h.digest()  # 得到密文
    response = conn.recv(len(digest))  # 接收客户端密文
    # hmac.compare_digest(密文,密文),比较客户端密文与服务端密文是否相同,相同返回True,不同返回False
    return hmac.compare_digest(response, digest)


def data_handler(conn, bufsize=1024):
    """
    判断链接是否合法
    :param conn: 管道
    :param bufsize: 接收数据长度
    :return: None
    """
    if not conn_auth(conn):
        print("该链接不合法")
        conn.close()
        return
    print("链接合法")
    while 1:
        data = conn.recv(bufsize)
        if not data:
            break
        conn.sendall(data.upper())


def server_handler(ip_port, bufsize, backlog=5):
    """
    只处理链接
    :param ip_port:地址(ip+port)
    :param bufsize:接收数据长度
    :param backlog:监听数
    :return:data_handler(conn, bufsize)
    """
    tcp_socket_server = socket.socket()  # 创建socket对象
    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", 8001)
    bufsize = 1024
    server_handler(ip_port, bufsize)
server端

客户端:

import socket
import hmac


secret_key = b"Jedan has a big key!"  #


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=1024):
    """
    发送密文验证,验证成功实现通信
    :param ip_port:地址
    :param bufsize:数据接收长度
    :return:None
    """
    tcp_socket_client = socket.socket()
    tcp_socket_client.connect(ip_port)

    conn_auth(tcp_socket_client)

    while 1:
        data = input(">>>(q退出)").strip()
        if not data:
            continue
        if data.upper() == "Q":
            break

        tcp_socket_client.sendall(data.encode("utf-8"))
        response = tcp_socket_client.recv(bufsize)
        print(response.decode("utf-8"))

    tcp_socket_client.close()


if __name__ == '__main__':
    ip_port = ("127.0.0.1", 8001)
    bufsize = 1024
    client_handler(ip_port, bufsize)
client端

猜你喜欢

转载自www.cnblogs.com/ipython-201806/p/10021392.html