python-socketserver_hashlib_文件校验_服务端合法性校验_tcp协议登录

1. 模块 socketserver

网络协议的最底层就是 socket , 基于原有 socket 模块 , 又封装了一层 , 就是 socketserver

socketserver : 为了实现 tcp 协议 server 端的并发

1.1 server 服务端
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()
1.2 client 客户端
import socket

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.connect(('127.0.0.1',9000))
# 处理收发数据的逻辑

sk.close()
2.1 server 服务端
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        """
		print(self.request)
		self.request <==> conn
		<socket.socket fd=4, family=AddressFamily.AF_INET, 
		type=SocketKind.SOCK_STREAM, proto=0,
		laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 49116)>
        
		print(self.client_address)
		self.client_address <==> addr ('127.0.0.1', 49116)
        """
        
        conn = self.request
        while True:
            # 接收数据
            msg1 = conn.recv(1024)
            msg = msg1.decode('utf-8')
            print(msg)
            conn.send(msg.upper().encode('utf-8'))
        
        print("handle方法被执行了")
        
# ThreadingTCPServer(ip端口号,自定义的类) 
server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),MyServer)
# 建立连接,循环调用
server.serve_forever()
2.2 client 客户端
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()    

2. hashlib 模块

hashlib 模块是一堆加密算法的集合体 , 哈希算法的加密方式不止一种

http://www.cmd5.com md5解密

应用场景: 在需要校验功能时使用

用户密码 => 加密,解密

相关校验 => 加密,解密

哈希算法也叫摘要算法 , 相同的数据始终得到相同的输出 , 不同的数据得到不同的输出

1. 哈希将不可变的任意长度的数据 , 变成具有固定长度的唯一值

2. 字典的键和集合的值是通过哈希计算存储的 , 存储的数据是散列(无序)

1. 密码加密
import hashlib
import random

# 1. 基本用法
# 1.1 创建一个 md5 算法对象
hm = hashlib.md5()
# 1.2 把要加密的字符串通过 update 更新到 hm 对象中运算
hm.update('123456'.encode('utf-8')) # 里面的数据必须是二进制字节流
# 1.3 获取32位16进制字符串
res = hm.hexdigest()
print(res , len(res))

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

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


# sha算法
"""
sha 算出来的十六进制的串是40位,加密稍慢,安全性稍高
md5 算出来的十六进制的串是32位,加密很快,安全性稍差
"""

hs = hashlib.sha1()
hs.update("我最是牛逼的tyert$#$^%*trhegdwerdfs".encode())
res = hs.hexdigest()
print(res, len(res))

hs = hashlib.sha512()
hs.update("123456".encode())
res = hs.hexdigest()
print(res , len(res))

# hmac 模块 
"""hmac 加密算法更加复杂,不容易破解"""
import hmac
# hmac.new(盐,密码)
key = b"a"
msg = b"123456"
hn = hmac.new(key,msg)
res = hn.hexdigest()
print(res, len(res)) # 32位长度 十六进制的字符串

# 动态加盐
import os

# os.urandom 返回随机的二进制字节流
res = os.urandom(32)
print(res,len(res))

key = os.urandom(32)
msg = b"123"
hn = hmac.new(key,msg)
res = hn.hexdigest()
print(res, len(res))
2. 文件校验
import hashlib
import os

"""
mode => r  read(数字->字符个数)
mode => rb read(数字->字节个数)
字节的个数 <=> 文件的大小
"""

# (1) 针对于小文件进行内容校验
def check_md5(filename):
	hs = hashlib.md5()
	with open(filename,mode="rb") as fp:			
		hs.update(fp.read())
	return hs.hexdigest()
	
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)

# 方法一
def check_md5(filename):
	hs = hashlib.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:
			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)
3. 服务端的合法性校验
1. server 服务端
# 服务端 (支付宝)
import socket
import os
import hmac

def auth(conn,secret_key):
    # 随机产生32位的二进制字节流
    msg = os.urandom(32)
    conn.send(msg)
    hn = hmac.new(secret_key.encode('utf-8'),msg)
    res_server = hn.hexdigest()
    print(res_server)
    # 服务端接收客户端发送过来的数据进行验证
    res_client = conn.recv(1024).decode('utf-8')
    
    if res_client == res_server:
        print('你是合法的服务端用户')
        return True
    else:
        print('不是合法的服务端用户')
        return Flase
    
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()
2. client 客户端
# 客户端 (公司)
import socket
import hmac

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 = '芝麻开门'
auth(sk,secret_key)

# 在验证成功之后,接收服务端发来的验证码
res = sk.recv(1024).decode('utf-8')
print(res)

sk.close()
4. tcp协议登录
1. server 服务端
import socket
import hashlib
import json

def get_md5_code(usr,pwd):
    hs = hashlib.md5(usr.encode())
    hs.update(pwd.encode())
    return hs.hexdigest()

sk = socket.socket()
sk.bind(("127.0.0.1",9000))
sk.listen()
conn,addr = sk.accept()

# 处理收发数据的逻辑
msg = conn.recv(1024).decode()
# 把反解之后的字符串恢复成原来的数据格式变成字典
dic = json.loads(msg)
print(dic)
sign = False
with open('user_info.txt',mode='r',encode='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}
            msg = json.dumps(res).encode('utf-8')
            conn.send(msg)
            sign = True
            break
            
if sign == False:
    # 发送错误的状态码
    res = {'code':0}
    msg = json.dumps(res).encode()
    conn.send(msg)
    
conn.close()
sk.close()
2. client 客户端
import socket
import json

sk.socket.socket()
sk.connect(('127.0.0.1',9000))

# 处理收发数据的逻辑
usr = input('请输入您的用户名: ').strip()
pwd = input('请输入您的密码: ').strip()
dic = {'username':usr,'password':pwd,'operate':'login'}
# 先通过json变成字符串
res = json.dumps(dic)
# json 字符串 -> 字节流
msg = res.encode()
# 把字节流发送给服务端
sk.send(msg)

# 接收服务端发送过来的数据
res = sk.recv(1024).decode()
dic_code = json.loads(res)

if dic_code['code']:
    print('恭喜您~登陆成功!')
else:
    print('I am so sorry ~ 登陆失败')
    
sk.close()    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I believe I can fly~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值