python3 网络编程之socketserver添加客户端认证机制

为了保证客户端的合法性,防止非法客户端连接服务端,可以通过在MyServer类中添加__auth_handler函数实现客户端合法性的验证。流程如下:

服务端:

1. 服务端通过os.urandom()生成随机32个字节字符串msg;

2. 将msg发送给客户端;

3. 通过hmac模块给msg加盐(secret_key)生成h;

4. 将h转换成数字;

5. 等待接收客户端返回验证消息response;

6. 将response与digest进行比较,如果一样返回True,不一样返回False;

7. 在handle方法中先验证response与digest,如果为True则继续执行通信循环,如果为False则关闭连接。

客户端:

1. 客户端连接服务端后即开始认证流程;

2. 接收服务端发来的32字节的随机字符串msg;

3. 通过hmac模块将盐加入到msg中;

4. 将msg转换成数字发送给服务端

服务端代码:

import socketserver
import os
import hmac


class MyServer(socketserver.BaseRequestHandler):
    def __auth_handler(self):
        print('开始验证客户端合法性')
        msg = os.urandom(32)
        self.request.sendall(msg)
        h = hmac.new(secret_key, msg)
        digest = h.digest()
        response = self.request.recv(len(digest))
        return hmac.compare_digest(digest, response)

    def handle(self):  # self代表连接实例
        print('conn is:', self.request)  # conn
        print('addr is:', self.client_address)  # addr

        if not self.__auth_handler():
            print('客户端验证失败,关闭连接')
            return
        print('合法连接开始了')

        while True:
            try:

                # 收消息
                data = self.request.recv(1024)
                if not data: break
                print('收到客户端的消息是:', data)

                # 发消息
                self.request.sendall(data.upper())
            except Exception as e:
                print(e)
                break


if __name__ == '__main__':
    secret_key = b'chenming bang bang'
    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8084), MyServer)
    s.serve_forever()  # 连接循环

合法客户端代码:

from socket import *
import hmac


def conn_auth(conn):
    msg = conn.recv(32)
    h = hmac.new(secret_key, msg)
    digest = h.digest()
    conn.sendall(digest)


def client_handler(ip_port, buffer_size=1024):
    tcp_client = socket(AF_INET, SOCK_STREAM)
    tcp_client.connect(ip_port)

    conn_auth(tcp_client)

    while True:

        msg = input('>:').strip()
        if not msg: continue
        if msg == 'quit': break
        tcp_client.sendall(msg.encode('utf-8'))
        data = tcp_client.recv(buffer_size)
        print('收到服务端的消息:', data.decode('utf-8'))


if __name__ == '__main__':
    ip_port = ('127.0.0.1', 8084)
    secret_key = b'chenming bang bang'
    client_handler(ip_port)

 非法客户端代码:

from socket import *


def client_handler(ip_port, buffer_size=1024):
    tcp_client = socket(AF_INET, SOCK_STREAM)
    tcp_client.connect(ip_port)


    while True:

        msg = input('>:').strip()
        if not msg: continue
        if msg == 'quit': break
        tcp_client.sendall(msg.encode('utf-8'))
        data = tcp_client.recv(buffer_size)
        print('收到服务端的消息:', data.decode('utf-8'))


if __name__ == '__main__':
    ip_port = ('127.0.0.1', 8084)
    client_handler(ip_port)

另外,如果非法客户端知道我们的认证方法,但是没有正确的secret_key也是无法验证客户端的合法性。 

 

 

你可能感兴趣的:(python全栈学习)