资源下载地址:https://download.csdn.net/download/sheziqiong/85596120
资源下载地址:https://download.csdn.net/download/sheziqiong/85596120
Uchat——基于 python 的安全即时通讯系统
目的
设计完成简易的安全即时通讯系统,实现类似于 QQ 的聊天软件;
需求分析
功能需求
-
聊天客户端
- 注册:用户与集中服务器通信完成注册,包括用户名、密码、邮箱、性别、年龄、数字证书等信息传输,其中数字证书包含公钥、用户名、邮箱等信息。私钥单独保存在客户端一个文件夹下不进行传输;能显示用户名、邮箱不符合格式规范或者重复,空输入等错误信息。
- 认证登录:客户端与集中服务器通信完成用户名、口令认证登录;能显示用户名、密码错误导致的登录错误信息。还有已登录账 再次登录时的多重登录检验,并将之前登陆的账 顶下去。
- 好友管理:用户可通过服务器进行搜索、添加、删除好友。
- 即时通信:用户通过客户端实现与好友的聊天,包括文字、图片传输。文字可实现字体颜色和大小的改变。
- 聊天记录:客户端能够保存聊天记录并且可以查看聊天记录。
- 消息加解密:采用 D-H 体制协商加密秘钥,用对称密码 AES 算法进行加解密。
- 消息摘要:使用 MD5 算法实现消息摘要认证功能,确保发送消息的完整性。
- 用户未读消息提醒:红点标注未读消息数目,并按最后发送消息时间排列好友列表。
- 用户离线后消息处理:用户上线后及时接收到离线时好友发送的消息。
功能结构图
-
高级功能
- 离线用户消息通知:暂时存储离线用户的消息,用户上线后,显示未读的消息并用红点标注;
- 好友在线离线功能实时更新;
- 限制账 只能一处登录:一个账 只能在一处登录,在别处登录时会把原先的登录踢下线;
- 支持群聊功能:可以创建群聊,并根据群 加入群聊;
- 聊天时字体大小颜色可更改;
- 支持聊天各类图像文件的缓存。
数据需求
-
客户端
客户端登录后加过的好友和加入的群聊需要从数据库中调出信息并在前端反馈呈现出来。客户端的聊天记录可以存储在数据库中,用到时直接读取返回消息历史。
-
集中服务器
-
users 表:用户信息表,存储用户基本信息,包括用户 ID(id)、用户名(username)、密码(password)、电子邮箱(email)、用户登录 IP 地址(ip)、用户登录端口(port)、性别(sex)、年龄(age)、公钥(pk)。
名称 数据类型 主键 是否唯一 是否为空 备注 id INTEGER Y Y N 用户 id username TEXT N Y N 用户名 password TEXT N Y N 密码 email TEXT N Y N 邮箱 ip TEXT N Y N 登录 IP port TEXT N Y N 登录端口 sex TEXT N Y N 性别 age TEXT N Y N 姓名 pk TEXT N Y N 公钥 -
friends 表:存储用户的好友信息,包括用户 id(from_user_id)、好友 id(to_user_id)、加好友请求是否接受(accepted)。
名称 数据类型 主键 是否唯一 是否为空 备注 from_user_id INTEGER Y Y N 本人 ID to_user_id INTEGER Y Y N 好友 ID accept BOOLEAN N N N 接受状态 -
chat_history 表:存储好友的聊天记录,包括发送方 ID(user_id)、接收方(target_id)ID(target_type)、聊天数据(data)(BLOB 类型存储二进制大对象,可以实现文件数据的直接存储),sent(用于标识消息是否已发送,若未发送,先存储这个操作,在某一次事件再次触发时检查标志位,操作服务端再次控制 client.socket 发送消息)。
名称 数据类型 主键 是否唯一 是否为空 备注 id INTEGER Y Y N 消息 ID user_id INTEGER N N N 用户 ID target_id INTEGER N N N 消息目标 ID target_type TEXT N N N 目标类型:群/用户 data BLOB N N N 消息体 sent BOOLEAN N N N 发送是否成功 -
rooms 表:群组表,包括该群组的主键 ID(id)、群组的名称(room_name)。
名称 数据类型 主键 是否唯一 是否为空 备注 id INTEGER Y Y N 群聊 ID room_name TEXT N Y N 群聊名 -
room_user 表:群组用户表,包括群组的 ID,群聊房间 (room_id)、加入该群组的用户(user_id)。
名称 数据类型 主键 是否唯一 是否为空 备注 id INTEGER Y Y N ID room_id INTEGER N N N 群聊 ID user_id INTEGER N N N 用户 ID
-
性能需求
-
可靠性需求
保证一个用户只能同时使用一个 IP 地址登录,客户端不会出现闪退、加密无效的情况。
-
安全性需求
客户端做好完整的封装;传输信息采用经过公钥加密机制协商的 AES 对称加密秘钥;服务器及时更新客户端 IP 地址等信息。
-
可维护性与可扩展性需求
对于软件功能方面,采用高内聚低耦合的模块化设计,包括登录模块、注册模块、好友列表模块、聊天模块等,确保每个模块的具有较高的独立性,使软件源码便于维护,同时便于后期添加聊天群等更多扩展内容,保证软件可以进行更新换代。
-
运行环境需求
-
客户端:python3
-
服务端:
python3
PC 硬盘容量:50G
运行内存:2G
-
UI 需求
- 页面内容:聊天字体大小和颜色可更改,主题突出,语言简单明了易懂,菜单设置合理、页面布局规范,文字准确,语言流畅。
- 技术环境:页面大小合适,无错误链接和空链接。
- 艺术风格:界面版面形象清晰,布局合理,字 大小适宜,字体选择合理,前后一致,动静搭配恰当,色彩和谐自然,与主题内容协调。
操作需求
- 所有弹出的窗口不超过一层,无层层堆叠的现象,不能无故为操作增加复杂度。
- 用户注册、用户登录、添加好友、删除好友聊天窗口的开启等所有操作务必要简单、快捷,限制在两次点击以内。
- 考虑到操作人员工作的实际环境状况,就要保证设计的按键足够的清晰足够大。
详细设计
系统结构说明
本系统的核心控制逻辑在于 C-S-C 之间发送的数据中包含了操作码,接收方通过对接收码的识别作出规定的操作。例如服务端接收添加好友的操作码会执行 add_friend.py。客户端接收操作码并不断把对应函数放入递归函数的队列中,由递归函数逐一执行队列中的函数。
系统主要分为三个部分:
- 聊天客户端(client)
- 集中服务器(server)
- 相互通信时的共同部分(common)
-
聊天客户端 client
实现安全即时通信系统的客户端,主要功能是通过界面与用户实现交互;通过 socket 与集中服务器进行通信,获得集中服务器的服务,实现用户的注册登录等功能。与好友即时通信和加入群聊通信。
- 登录模块 LoginForm
该模块创建登录界面并可链接到注册界面,若输入为空则 错,否则将获取用户输入的用户名和密码打包成登录请求消息(MessageType.login)发送给服务器,服务器根据消息类型和数据包中的内容以及在数据库查找到的结果进行判断,根据不同情况发送不同的反馈给客户端。客户端收到反馈消息,若 data[‘type’]为 login_failed,则用户名和密码输入有误;若为 data[‘type’]为 login_successful 则根据 memory 进入登录后显示好友列表的 ContractsForm 界面。 - 注册模块 RegisterForm
该模块只有在登录界面点击注册按钮时才会显示。通过注册窗口获得用户输出的个人信息:用户名、密码、邮箱、性别、年龄,若其中用户名、邮箱、密码为空或两次密码输入不一致则会提示相应的错误以引导用户进行正确的输入,否则将获取用户输入打包成注册请求消息(MessageType.register)发送给服务器。服务器查找数据库判断是否用户名已经注册过,发送不同反馈给用户,若 data[‘type’]为 username_taken,则用户名已被注册,若 data[‘type’]为 MessageType.register_successful 则注册成功,并且在客户端生成证书包含用户的用户名,邮箱,公钥。 - 主界面 ContactsForm
该模块在用户登录成功以后显示。显示好友列表中好友的用户名、在线状态,ip 地址及端口 等。下方的按钮有添加好友、删除好友、添加群聊、创建群聊。可以点击相应的按钮进行相应的操作,发给服务器相应的数据包,服务器接收到数据包后进行解析,根据不同类型进行 event_handler。若点击好友列表或群聊即可跳出聊天界面进行聊天。未读的消息会用红点标注,根据最后一条消息的发送时间来对好友列表排序。 - .聊天界面 ChatForm
该模块是用户与好友聊天的界面。当用户在好友列表中点击好友列表时,即向好友发出聊天,服务器收到聊天请求后寻找对方的证书,找到对方的公钥,双方使用 Diffie-Hellman 算法协商算法,然后利用 AES 加密消息保证消息的机密性,MD5 生成消息摘要验证保证消息的完整性。另外还可以更改聊天过程中字体的大小和颜色,支持多行输入,支持发送文件,以图片为例,将保存聊天过程中的接收到的图片,并识别其格式。 - 客户端部件(components)模块
该模块实现 tkinter 静态部件添加和滚动模块的实现。 - 客户端 memory 管理模块(memory)
该模块用于初始化 tkinter 对象 tk 的属性,如窗口,secure_channel 对象等。 - 多用(util)中的 socket_listener 模块
该模块用于客户端处理消息类型,文本或其他。以及不断循环建立连接 socket 接收消息,实现数据包的完整接收。定义处理给好友框,消息框更新历史消息的函数,事件操作的监听函数和移除函数,消息的监听函数和移除函数。可以实现接收数据并且拼成块,更新聊天的历史记录,通知客户端更新 contacts 界面上的最后一条消息的内容,时间,未读消息的数目等。
- 登录模块 LoginForm
-
集中服务器 server
- event_handler 模块
该模块分为 11 个部分,分别具体处理客户端发来的各个操作事件。如登录加好友删除好友等操作。 - database 数据库模块
该模块主要是根据客户端触发的事件对数据库的各种操作。 - broadcast 广播模块
该模块主要是针对群聊,为群组中的每个在线用户广播发送消息。 - memory 模块
定义用户与 secure_channel 对象互相映射的字典列表,所有已经建立的 secure_channel 对象,以及用户下线后将其从在线 secure_channel 对象列表中移除的操作。
- event_handler 模块
-
客户端服务器公用模块 common
- message 模块
将变量数据等变成可存储或者传输的过程即序列化,同时还将各个事件的类型变为枚举变量保存,将收到的数据包反序列化进行恢复,再提取数据包中 Message 的类型。 - cryptography 模块
用于调用其生成公钥,然后从证书中获取公钥,再使用 D-H 算法协商生成共享密钥。 - prime 模块
该模块主要是判断是否为素数,生成大素数,为证书的生成提供基础。 - secure_channel 模块
该模块主要是定义 secure_channel 类,即包裹了 socket 和参数秘钥的封装对象。在通信对象之间协商好对称加密秘钥之后封装在这个新的对象中。并且这个对象对数据有新的函数功能:- send 函数
用于对发送的序列化之后的数据用对称加密秘钥进行 AES 加密并用 struct 结构体将其打包成自设协议格式的数据包。 - on_data
函数主要用于接受数据的逆向解析。按照要求配置 socket 和数据传输的格式进行规则化。数据包的格式为前四个字节为消息体的长度,接着一字节存储 AES 加密时的消息填充长度,然后 16 字节 AES 加密时所需要的初始值,再接着是 32 字节的消息摘要,最后才是加密后的消息体。
- send 函数
- message 模块
重要数据说明
-
发送接收的数据格式
安全传输
-
数据包结构
-
消息加密算法:AES 对称加密算法,保证消息机密性
-
消息摘要算法:MD5 算法,保证消息的完整性
-
包结构分析
-
第一层(解密前)
通过函数 struct.pack()构造加密的数据包,结构如下
-
MessageType:event_handler_map()规定的操作码
-
第四层,基础数据部分
包括 int、str、bool、float、binary 等
客户端的证书、公钥、私钥
-
-
程序函数清单
客户端函数
-
socket_listener(self,data)
-
位置
- client/forms/register_form.py
- client/forms/login_form.py
- client/forms/contacts_form.py
- client/forms/chat_form.py
-
参数
- self:所在的类的自身
- data:监听数据
-
功能
在注册、登录、好友列表、聊天框四个页面建立事件监听,解析监听 data,确定数据中 MessageType 的类型,在 register_form.py 文件中用于判断用户名是否被占用、返回注册结果;在 login_form.py 中用于返回登录结果;在 contacts_form.py 文件中用于判断是否处理添加、删除好友、添加、创建群聊以及执行操作的结果、判断好友是否下线并刷新好友列表。
-
-
remove_socket_listener_and_close(self)
-
位置
- client/forms/register_form.py
- client/forms/login_form.py
- client/forms/contacts_form.py
- client/forms/chat_form.py
-
参数
- self:所在的类的自身:RegisterForm、LoginForm、ContactsForm、ChatForm
-
功能
通过调用 util/socket_listener 文件下的 remove_listener 函数来关闭事件监听,同时调用库函数 destroy()关闭窗口、清空客户端缓存信息。
-
-
_init_(self,master=None)
-
位置
- client/forms/register_form.py
-
参数
- self:所在类 RegisterForm 自身
- master:注册主窗口用来容纳其他组件,默认一个窗口 master=None
-
功能
通过库函数 super()实现子类__init__()对父类__init__()的继承;对注册窗口进行布局,包括确定注册界面的长宽,确定背景、标签、输入框、按钮等的位置、颜色、类型、链接等;初始化安全信道;通过 socket_listener()函数和 remove_socket_listener_and_close()函数控制对客户端 socket 事件监听和关闭。
-
-
do_register(self)
-
位置
- client/forms/register_form.py
-
参数
- self:所在类 RegisterForm 自身
-
功能
检查输入的用户名、密码、邮箱是否合法;判断两次输入的密码是否相同;调用 get_ip()函数获取客户端的 IP 地址和端口 ;向服务器发送注册请求,并通过调用函数 send()将注册输入的用户名、密码、邮箱、性别、年龄以及用户的 IP 地址和端口 等信息发送给服务器;构造数字证书,命名为 IP 地址 +“——cert.pem”,内容为用户名 + 邮箱 + 用户公钥
-
-
._init_(self,master=None)
-
位置
- client/forms/login_form.py
-
参数
- self:所在类 RegisterForm 自身
- master:登录主窗口用来容纳其他组件,默认一个窗口 master=None
-
功能
通过库函数 super()实现子类__init__()对父类_init_()的继承;对登录窗口进行布局,包括确定注册界面的长宽,确定背景、标签、输入框、按钮等的位置、颜色、类型、链接等;初始化安全信道;通过 socket_listener()函数和 add_listener()函数将服务器端加入到监听列表中。
-
-
do_login(self)
-
位置
- client/forms/login_form.py
-
参数
- 参数 self:所在类 LoginForm 自身
-
功能
检查输入的用户名、密码是否合法;通过调用函数 send()向服务器发送登录请求,并将输入的用户名、密码等信息发送给服务器。
-
-
show_register(self)
-
位置
- client/forms/login_form.py
-
参数
- self:所在类 LoginForm 自身
-
功能
与注册按钮关联,通过点击按钮调用库函数 Toplevel()跳转到注册页面。
-
-
._init_(self,master=None)
-
位置
- client/forms/contacts_form.py
-
参数
- self:所在类 ContactsForm 自身
- master:登录主窗口用来容纳其他组件,默认一个窗口 master=None。
-
功能
通过库函数 super()实现子类_init__()对父类__init_()的继承;对好友列表窗口布局,确定好友列表的长宽、按钮的位置、颜色、类型、链接等;调用 VerticalScrolledFrame()函数,将列表设置滚动条 + 图片背景;初始化安全信道;通过 socket_listener()函数和 remove_socket_listener_and_close()函数控制对客户端 socket 事件监听和关闭。
-
-
refresh_contacts(self)
-
位置
- client/forms/contacts_form.py
-
参数
- self:所在类 ContactsForm 自身
-
功能
通过比较与好友或群聊最近一次发消息的时间 last_message_timestamp 和好友的在线情况刷新好友列表,根据好友或群聊发送消息的时间远近对好友列表进行排列,并将在线好友移至列表顶部
-
-
on_add_friend(self)/on_del_friend(self)/on_add_room(self)on_create_room(self)
-
位置
- client/forms/contacts_form.py
-
参数
- self:所在类 ContactsForm 自身
-
功能
与添加好友、删除好友、添加群聊、创建群聊四个按钮链接;使用库函数 simpledialog.askstring()弹出输入框,并对输入的内容进行检验;使用函数 send()向服务器发送操作请求。
-
-
handle_new_contact(self,data)
-
位置
- client/forms/contacts_form.py
-
参数
- self:所在类 ContactsForm 自身
- data:接收的数据
-
功能
被该文件下的另一个函数__init__()调用用来添加或删除列表中的好友。
-
-
_init_(self,target,master=None)
-
位置
- client/forms/chat_form.py
-
参数
- self:所在类 ChatFrame 自身
- target:一个用来暂时存储消息的列表
- master:聊天框主窗口用来容纳其他组件,默认一个窗口 master=None
-
功能
对聊天框布局,确定聊天框的长宽、输入框、消息框、按钮的位置、颜色、类型、链接等;分辨私人聊天和群聊;利用 append_to_chat_box()函数加载、更新历史消息。
-
-
send_message(self)/send_file(self)
-
位置
- client/forms/chat_form.py
-
参数
- self:所在类 ChatFrame 自身
-
功能
通过调用 input_textbox.get()函数和 filedialog.askopenfilename()函数实现发送消息和文件。
-
-
digest_message(self,data)
-
位置
- client/forms/chat_form.py
-
参数
- self:所在类 ChatFrame 自身
- data:传输的数据
-
功能
通过分析传输的数据包,摘取消息的时间戳、发送者、消息类型,为布局做准备。
-
-
_init_(self,parent,onclick)
-
位置
- client/components/contact_item.py
-
参数
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!
-
-