验证客户端链接的合法性

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

例1:简单的服务端如下
#!/usr/bin/env python
# _*_ coding: utf-8 _*_import os
import socket
import hmacsecret_key = '老衲洗头用飘柔'.encode('utf-8')
server = socket.socket()
server.bind(('127.0.0.1', 9527))
server.listen()
while True:try:conn, addr = server.accept()random_bytes = os.urandom(32)conn.send(random_bytes)hmac_obj = hmac.new(key=secret_key, msg=random_bytes)ret = hmac_obj.hexdigest()print(hmac_obj.hexdigest())msg = conn.recv(1024).decode('utf-8')if msg == ret:print('是合法的客户端')else:print('不是合法的客户端')conn.close()finally:server.close()break客户端如下:
#!/usr/bin/env python
# _*_ coding: utf-8 _*_import socket
import hmacsecret_key = '老衲洗头用飘柔'.encode('utf-8')
client = socket.socket()
client.connect(('127.0.0.1', 9527))urandom = client.recv(1024)
hmac_obj = hmac.new(key=secret_key, msg=urandom)
client.send(hmac_obj.hexdigest().encode('utf-8'))
print('--------')
client.close()效果如下:
33e40f5f66b2e9b2867a7862d02fba9d
是合法的客户端。例2:TCP时间戳服务器验证
#!/usr/bin/env python
# _*_ coding: utf-8 _*_import os
import hmac
from socket import *
from time import ctime'''
socket tcp时间戳服务端,利用hmac模块加盐验证客户端连接的合法性
'''# 加盐
secret_key = '芝麻开门'.encode('utf-8')def conn_auth(conn):'''认证客户端链接:param conn: 客户端链接:return: True or False'''print('开始验证新链接的合法性')# os模块生成随机32位字符串,用于发送给客户端验证ustr = os.urandom(32)conn.sendall(ustr)# 生成密钥 hmac加盐+32位随机字符串cipher = hmac.new(secret_key, ustr).digest()# 接收客户端发送过来的密钥,长度和这边生成的应当一致result = conn.recv(len(cipher))# compare 两相比较,一致返回true,否则为falsereturn hmac.compare_digest(result, cipher)def data_handler(conn,bufsize=1024):# 如果验证不通过if not conn_auth(conn):print('链接非法,关闭')conn.close()returnprint('链接已通过验证,开始通信')while True:data = conn.recv(bufsize)if not data:breakdata = '[%s] %s' % (ctime(), data.decode('utf-8'))conn.sendall(data.encode('utf-8'))conn.close()def server_handler(host,port,bufsize=1024,num=5):'''socket tcp服务端设置:param host: 主机名或ip地址:param port: 端口号:param bufsize: 缓冲区大小,默认1024:param num: 侦听最大客户端,默认5位:return: '''tcpss = socket(AF_INET, SOCK_STREAM)tcpss.bind((host,port))tcpss.listen(num)while True:conn, addr = tcpss.accept()print('新连接[%s:%s]' % (addr[0], addr[1]))data_handler(conn,bufsize)if __name__ == '__main__':host = 'localhost'port = 9527server_handler(host, port)TCP时间戳客户端:
#!/usr/bin/env python
# _*_ coding: utf-8 _*_'''
socket tcp时间戳客户端,利用hmac模块加盐验证客户端连接的合法性
'''import os
import hmac
from socket import *secret_key = '芝麻开门'.encode('utf-8')def conn_auth(conn):'''验证客户端到服务器的链接:param conn: 链接:return: True or False'''# 客户端接收32位随机字节ustr = conn.recv(32)# hmac加盐加密文得出最终密钥并发送回服务端cipher = hmac.new(secret_key, ustr).digest()conn.sendall(cipher)def client_handler(host,port,bufsize=1024):tcpsc = socket(AF_INET, SOCK_STREAM)tcpsc.connect((host, port))conn_auth(tcpsc)while True:data = input('>>>').strip()if not data:continueif data == 'quit':breaktcpsc.sendall(data.encode('utf-8'))result = tcpsc.recv(bufsize)print(result.decode('utf-8'))tcpsc.close()if __name__ == '__main__':host = 'localhost'port = 9527bufsize = 1024client_handler(host, port, bufsize)效果:
服务端:
D:\PortableSoft\Python35\python.exe E:/Python/重要的代码/socket_hmac验证合法连接/tcpss.py
新连接[127.0.0.1:57600]
开始验证新链接的合法性
链接已通过验证,开始通信客户端:
D:\PortableSoft\Python35\python.exe E:/Python/重要的代码/socket_hmac验证合法连接/tcpsc.py
>>>time
[Thu May 10 22:00:19 2018] time
>>>也许猪的身体不优美,长鼻短尾,但是别人不可天空里高飞
[Thu May 10 22:01:10 2018] 也许猪的身体不优美,长鼻短尾,但是别人不可天空里高飞
>>>

socketserver

SocketServer是标准库中的一个高级模块(python3.x中重命名为socketserver),
它的目标是简化很多样板代码,它们是创建网络客户端和服务器所必需的代码。
这个模块中有为你创建的各种各样的类,如下表所示:

除了为你隐藏了实现细节之外,另一个不同之处是,我们现在使用类来编写应用程序,
以面向对象的方式处理事务有助于组织数据,以及逻辑性地将功能放在正确的地方。
你还会注意到,应用程序现在是事件驱动的,这意味着只有在系统中的事件发生时,它们才会工作。

事件包括消息的发送和接收。

事实上,你会看到类定义只包括一个用来接收客户端消息的事件处理程序。
所有其它的功能都来自使用的SocketServer类。
在原始服务器循环中,我们阻塞等待请求,当接收到请求时就对其提供服务,然后继续等待。
在此处的服务器循环中,并非在服务器中创建代码,而是定义一个处理程序,
这样当服务器接收到一个传入的请求时,服务器就可以调用你的函数。

创建SocketServer TCP服务器

#!/usr/bin/env python
# _*_ coding: utf-8 _*_'''
通过使用socketserver类、TCPServer和StreamRequesthandler,该脚本创建了一个时间戳TCP服务器。
'''from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH)
from time import ctimeHOST = '127.0.0.1'
PORT = 9527
ADDR = (HOST, PORT)class MyRequestHandler(SRH):# 重写handle方法,该方法在基类Request中默认情况下没有任何行为(pass)
# 但当接收到一个客户端的消息时,它就会调用handle()方法,因此得重写进行处理。def handle(self):print('...connected from:', self.client_address)# StreamRequsetHandler将输入和输出套接字看作类似文件的对象# 因此可以使用readline()获取客户端消息,当然此时客户端要约定消息附带\n换行符data = '[%s] %s' % (ctime(), self.rfile.readline().decode('utf-8'))# 同理,视作文件对象,使用write()将字符串发送回客户端self.wfile.write(data.encode('utf-8'))tcpServ = TCP(ADDR, MyRequestHandler)
print('waiting for connection...')
# 注:是serve,而不是server;forever为无限循环地等待并服务于客户端请求。
tcpServ.serve_forever()创建SocketServer TCP客户端
#!/usr/bin/env python
# _*_ coding: utf-8 _*_from socket  import *HOST = 'localhost'
PORT = 9527
BUFSIZ = 1024
ADDR = (HOST, PORT)while True:'''和之前socker普通的tcp客户端从输入才开始循环不同,sockerserver请求处理程序的默认行为是接受连接、获取请求,然后关闭连接。由于这个原因,我们不能在应用程序整个执行过程中都保持连接,因此每次向服务器发送消息时,都需要创建一个新的套接字。'''tcpCliSock = socket(AF_INET, SOCK_STREAM)tcpCliSock.connect(ADDR)data = input('>>>')if not data:break'''这里使用的处理程序对待套接字通信就像是文件一样,所以必須发送行终止符(回车和换行符)。而服务器只是保留并重用这里发送的终止符。'''data = '%s\r\n' % datatcpCliSock.send(data.encode('utf-8'))resu = tcpCliSock.recv(BUFSIZ)if not resu:break# 加strip()处理掉换行符print(resu.decode('utf-8').strip())tcpCliSock.close()运行服务端和客户端后效果如下:
client端:
>>>百变星君
[Wed May  9 20:44:11 2018] 百变星君
>>>大圣娶亲
[Wed May  9 20:44:22 2018] 大圣娶亲
>>>
server端:
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 53286)
----------------------------------------
...connected from: ('127.0.0.1', 53397)
...connected from: ('127.0.0.1', 53398)
...connected from: ('127.0.0.1', 53399)另一种不看成文件操作的支持并发连接的TCP时间戳服务器和客户端如下:
socketserver TCP时间戳服务器
#!/usr/bin/env python
# _*_ coding: utf-8 _*_import socketserver
from time import ctime# 并发编程
class MyServer(socketserver.BaseRequestHandler):def handle(self):print('...连接来自:', self.client_address)msg = self.request.recv(1024)msg = '[%s] %s' % (ctime(), msg.decode('utf-8'))print(msg)self.request.send(msg.encode('utf-8'))if __name__ == '__main__':# 支持重用端口和Ipsocketserver.TCPServer.allow_reuse_address = True# ThreadingTCPServer 支持线程功能server = socketserver.ThreadingTCPServer(('127.0.0.1', 9527), MyServer)print('等待连接...')server.serve_forever()socketserver TCP时间戳客户端
#!/usr/bin/env python
# _*_ coding: utf-8 _*_import socketwhile True:client = socket.socket()client.connect(('127.0.0.1', 9527))data = input('>>>')if not data:breakclient.send(data.encode('utf-8'))resu = client.recv(1024)if not resu:breakprint(resu.decode('utf-8'))client.close()运行效果如下:
第一个client端:
>>>哆啦A梦
[Wed May  9 20:59:14 2018] 哆啦A梦
>>>蜡笔小新
[Wed May  9 20:59:27 2018] 蜡笔小新
>>>超人迪加
[Wed May  9 21:00:13 2018] 超人迪加
>>>
第二个client端:
>>>银河唯一的秘密
[Wed May  9 20:59:50 2018] 银河唯一的秘密
>>>护卫人类,挽救地球,看守这宇宙
[Wed May  9 21:00:35 2018] 护卫人类,挽救地球,看守这宇宙
>>>
socketserver服务端:
等待连接...
...连接来自: ('127.0.0.1', 53505)
[Wed May  9 20:59:14 2018] 哆啦A梦
...连接来自: ('127.0.0.1', 53506)
[Wed May  9 20:59:27 2018] 蜡笔小新
...连接来自: ('127.0.0.1', 53507)
...连接来自: ('127.0.0.1', 53508)
[Wed May  9 20:59:50 2018] 银河唯一的秘密
...连接来自: ('127.0.0.1', 53509)
[Wed May  9 21:00:13 2018] 超人迪加
...连接来自: ('127.0.0.1', 53510)
[Wed May  9 21:00:35 2018] 护卫人类,挽救地球,看守这宇宙
...连接来自: ('127.0.0.1', 53514)

end

参考:
http://www.cnblogs.com/Eva-J/
《python核心编程第四版》

转载于:https://www.cnblogs.com/tielemao/p/9022939.html

铁乐学Python_Day35_Socket模块3和hmac模块相关推荐

  1. Python基础教程:hashlib和hmac模块

    一.hashlib模块 1 hash是什么 hash是一种算法(Python3.版本里使用hashlib模块代替了md5模块和sha模块,主要提供 SHA1.SHA224.SHA256.SHA384. ...

  2. Python学习笔记:常用内建模块4:hmac

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  3. SocketServer模块,hmac模块验证client合法性

    hmac模块: 1.模块初识: import hmac # h = hmac.new() #括号里要给它连个bytes类型,一个是自定义的secret_key,一个是你想进行加密的bytes # 密文 ...

  4. python加密模块教程_Python加密模块的hashlib,hmac模块使用解析

    这篇文章主要介绍了Python加密模块的hashlib,hmac模块使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在写搬砖脚本中,碰到一个 ...

  5. Python hashlib、hmac模块

    Python中的用于加密的函数位于hashlib,hmac模块中,都是内置模块,直接导入即可使用 hashlib模块实现了md5,sha1,sha224,sha256,sha384,sha512等算法 ...

  6. python hmac_Python之hmac模块的使用

    hmac模块的作用: 用于验证信息的完整性. 1.hmac消息签名(默认使用MD5加算法) #!/usr/bin/env python#-*- coding: utf-8 -*- importhmac ...

  7. 铁乐学python_Day42_锁和队列

    铁乐学python_Day42_锁和队列 例:多个线程抢占资源的情况 from threading import Thread import timedef work():global ntemp = ...

  8. python hashlib模块安装_python hashlib 模块

    hashlib模块用于加密相关的操作,代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法. 在python3中已经废弃了md5和sha模 ...

  9. php 5.2 模块路径,5.2 模块和操作

    # 模块和操作 [上一页](# "上一页")[下一页](# "下一页") ThinkPHP采用模块和操作的方式来执行,首先,用户的请求会通过入口文件生成一个应用 ...

最新文章

  1. Linux之cp和mv命令选项
  2. Python自动化开发学习2
  3. Kubenetes — YAML 基本语法
  4. 左转待转区----当同向直行信号灯绿灯亮时,左转弯的车辆进入左转待转区等候放行信号(即使此时左转弯灯是红色的) 注意:当直行红灯时候禁止进入...
  5. 【SQL】SQL语句多表联合查询
  6. ElementUI中el-upload怎样上传文件并且传递额外参数给Springboot后台进行接收
  7. python函数体以冒号起始、并且是缩进格式的_Python基础第三课
  8. Dataphin产品核心功能大图(六)发布中心:生产和开发隔离模式下的保护伞
  9. IceSword偏门功能介绍
  10. 机器学习 | 早期停止法原理及Python实现
  11. C#中各种数组的性能比较
  12. Longest Subsequence CodeForces - 632D (lcm)
  13. php小程序支付notify,PHP 小程序支付
  14. mysql show命令原理_MySQL show processlist;命令详解
  15. 远程登录shell命名sftp_开发好物推荐13强于XShell远程连接FinalSHell
  16. 树莓派3B的摄像头模块
  17. 法律基础(第六版)4
  18. 丽江旅游线路规划丽江游玩小贴士丽江游玩攻略花费
  19. 2017 多校4 Wavel Sequence
  20. 【深度学习】Github 最受欢迎的深度学习项目 TOP 20

热门文章

  1. 2022-2028年中国领带行业投资分析及前景预测报告
  2. C/C++ 编程规范(01 )— 排版
  3. \r \r\n \t的区别
  4. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))) TNS-12541: TNS:no li
  5. 客快物流大数据项目(八):Docker的安装和启动
  6. 2021年大数据ELK(一):集中式日志协议栈Elastic Stack简介
  7. Could not download lint-gradle.jar (com.android.tools.lint:lint-gradle:26.4.
  8. HBuilder 的快捷键
  9. Java中byte与16进制字符串的互相转换
  10. 用 Hystrix 构建高可用服务架构