这是一个基于Flask的后端API程序,适用于Linux系统,提供玩家信息管理、对战记录管理等功能。
- 玩家信息管理(创建、查询、更新)
- 对战记录管理(添加、查询)
- 密码加密存储
- 基于本机IP的API访问
如果您的Windows系统上尚未安装Python,请从Python官网下载并安装最新版本。安装时请勾选"Add Python to PATH"选项。
打开命令提示符(cmd)或PowerShell,执行以下命令:
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境
# 在命令提示符中:
venv\Scripts\activate
# 在PowerShell中(可能需要以管理员身份运行):
.\venv\Scripts\Activate.ps1pip install -r requirements.txt您可以直接运行Python脚本:
python main.py或者使用我们提供的Windows启动脚本:
# 双击运行或在命令行中执行
start_api.batdeactivate我们提供了start_api.bat脚本,可以自动完成以下操作:
- 检查Python是否已安装
- 自动创建虚拟环境(如果不存在)
- 激活虚拟环境
- 安装所需依赖
- 启动API服务器
您只需双击该脚本即可开始使用API。
在Linux系统上,您可能会遇到"externally-managed-environment"问题。这是因为较新的Debian/Ubuntu系统采用了PEP 668规范来管理包环境。请按照以下步骤操作:
# 创建虚拟环境
python3 -m venv venv
# 激活虚拟环境
source venv/bin/activatepip install -r requirements.txtpython main.pydeactivate您也可以创建一个简单的启动脚本来自动化上述过程:
#!/bin/bash
# 创建并激活虚拟环境
if [ ! -d "venv" ]; then
python3 -m venv venv
fi
source venv/bin/activate
# 安装依赖
pip install -r requirements.txt
# 运行API程序
python main.py将上述内容保存为start_api.sh,然后运行:
chmod +x start_api.sh
./start_api.sh程序将在端口5000上运行,可以通过本机IP地址访问API。
-
获取所有玩家信息
- 方法:GET
- 地址:
http://本机IP:5000/api/players - 返回:所有玩家的详细信息
-
创建新玩家
- 方法:POST
- 地址:
http://本机IP:5000/api/players - 请求体:
{ "nickname": "玩家昵称", "email": "玩家邮箱", "password": "玩家密码" } - 返回:新创建的玩家信息
-
获取单个玩家信息
- 方法:GET
- 地址:
http://本机IP:5000/api/players/<player_id> - 返回:指定玩家的详细信息
-
更新玩家昵称
- 方法:PUT
- 地址:
http://本机IP:5000/api/players/<player_id>/nickname - 请求体:
{ "nickname": "新昵称" } - 返回:更新后的玩家信息
-
更新玩家邮箱
- 方法:PUT
- 地址:
http://本机IP:5000/api/players/<player_id>/email - 请求体:
{ "email": "新邮箱" } - 返回:更新后的玩家信息
-
更新玩家密码
- 方法:PUT
- 地址:
http://本机IP:5000/api/players/<player_id>/password - 请求体:
{ "current_password": "当前密码", "new_password": "新密码" } - 返回:更新成功的消息
-
添加对战记录
- 方法:POST
- 地址:
http://本机IP:5000/api/players/<player_id>/battle_records - 请求体:
{ "opponent": "对手昵称", "result": "比赛结果", # win, lose, draw "score": "比赛分数", "timestamp": "时间戳" # 可选 } - 返回:新添加的对战记录
-
获取对战记录
- 方法:GET
- 地址:
http://本机IP:5000/api/players/<player_id>/battle_records - 返回:指定玩家的所有对战记录
本API使用bcrypt库实现安全的密码加密存储,加密流程如下:
-
密码加密过程:
- 系统使用
bcrypt.gensalt()生成随机的加密盐值(salt) - 将用户输入的明文密码转换为UTF-8字节码
- 使用
bcrypt.hashpw()函数将密码与盐值结合进行哈希计算 - 最终将加密后的密码解码为字符串存储在JSON文件中
- 系统使用
-
密码验证机制:
- 当用户需要验证密码(如更新密码时),系统使用
bcrypt.checkpw()函数 - 该函数会自动提取存储密码中的盐值,并使用相同的算法重新计算哈希
- 比较计算结果与存储的哈希值是否匹配,无需存储明文密码
- 当用户需要验证密码(如更新密码时),系统使用
-
安全特性:
- 即使两个用户使用相同的密码,由于随机盐值的存在,存储的哈希值也会不同
- bcrypt是专门为密码存储设计的哈希函数,包含自适应特性,可以随着硬件性能提升调整计算难度
项目中包含一个password_encrypt_demo.py脚本,用于直观演示密码加密和验证过程:
- 确保已安装bcrypt库(
pip install bcrypt) - 运行脚本:
python password_encrypt_demo.py - 脚本会展示:
- 原始明文密码到加密哈希的转换过程
- 密码验证的工作原理
- 相同密码使用不同盐值生成不同哈希的安全特性
通过这个演示,您可以更好地理解系统如何安全地存储和验证密码。
程序使用JSON文件(players.json)存储所有数据,包括玩家信息和对战记录。
对战数据是作为每个玩家对象的一部分存储在同一个JSON文件中,具体结构如下:
-
存储位置:所有对战记录都存储在
players.json文件中,作为每个玩家对象的一个字段 -
数据结构:
- 每个玩家对象包含一个
battle_records数组字段 - 每次添加对战记录时,系统会生成一个新的唯一ID(使用UUID)
- 每条对战记录包含以下信息:
id: 对战记录唯一标识opponent: 对手名称result: 对战结果(win/lose/draw)score: 对战得分timestamp: 对战时间戳(可选,默认为数据文件最后修改时间)
- 每个玩家对象包含一个
-
数据存储流程:
- 当通过
/api/players/<player_id>/battle_records端点添加对战记录时 - 系统会读取整个players.json文件
- 将新的对战记录添加到对应玩家的
battle_records数组中 - 然后将更新后的所有数据写回到players.json文件
- 当通过
-
数据访问方式:
- 可以通过
/api/players/<player_id>/battle_records端点获取特定玩家的所有对战记录 - 也可以通过
/api/players/<player_id>端点获取包含对战记录在内的完整玩家信息
- 可以通过
由于bcrypt是单向哈希函数,设计目的就是为了防止密码被解密,因此无法直接将存储的密码哈希值转换回原始密码。
为了方便测试和验证密码,我们提供了一个密码验证工具:
这是一个命令行工具,用于验证输入的密码是否与存储在系统中的密码哈希值匹配。
使用方法:
- 在命令行中运行:
python password_checker.py - 程序会自动列出所有注册的玩家信息
- 输入要验证的玩家ID
- 输入要验证的密码
- 程序会告诉你密码是否正确
注意:这个工具仅用于验证密码是否匹配,而不是解密密码。
在Windows系统上,您有多种方法可以测试API:
Windows 10及以上版本的PowerShell内置了Invoke-RestMethod和Invoke-WebRequest命令,可以直接用于API测试。
Windows 10版本1803及以上已经预装了curl命令,您可以在命令提示符或PowerShell中直接使用。
您也可以使用Postman、Insomnia等第三方API测试工具来测试API。
以下是Windows环境下的API测试示例:
使用curl (Windows 10 1803+):
curl -X POST http://localhost:5000/api/players ^
-H "Content-Type: application/json" ^
-d '{"nickname": "testplayer", "email": "test@example.com", "password": "testpassword"}'使用PowerShell:
Invoke-RestMethod -Uri http://localhost:5000/api/players -Method POST -Headers @{"Content-Type"="application/json"} -Body '{"nickname": "testplayer", "email": "test@example.com", "password": "testpassword"}'使用curl:
curl http://localhost:5000/api/players使用PowerShell:
Invoke-RestMethod -Uri http://localhost:5000/api/players -Method GET使用curl:
# 替换为实际的玩家ID
curl http://localhost:5000/api/players/player_id_here使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here -Method GET使用curl:
# 替换为实际的玩家ID
curl -X PUT http://localhost:5000/api/players/player_id_here/nickname ^
-H "Content-Type: application/json" ^
-d '{"nickname": "new_nickname"}'使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here/nickname -Method PUT -Headers @{"Content-Type"="application/json"} -Body '{"nickname": "new_nickname"}'使用curl:
# 替换为实际的玩家ID
curl -X POST http://localhost:5000/api/players/player_id_here/battle_records ^
-H "Content-Type: application/json" ^
-d '{"opponent": "opponent1", "result": "win", "score": "100-80"}'使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here/battle_records -Method POST -Headers @{"Content-Type"="application/json"} -Body '{"opponent": "opponent1", "result": "win", "score": "100-80"}'使用curl:
# 替换为实际的玩家ID
curl -X PUT http://localhost:5000/api/players/player_id_here/email ^
-H "Content-Type: application/json" ^
-d '{"email": "new_email@example.com"}'使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here/email -Method PUT -Headers @{"Content-Type"="application/json"} -Body '{"email": "new_email@example.com"}'使用curl:
# 替换为实际的玩家ID
curl -X PUT http://localhost:5000/api/players/player_id_here/password ^
-H "Content-Type: application/json" ^
-d '{"current_password": "old_password", "new_password": "new_password"}'使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here/password -Method PUT -Headers @{"Content-Type"="application/json"} -Body '{"current_password": "old_password", "new_password": "new_password"}'使用curl:
# 替换为实际的玩家ID
curl http://localhost:5000/api/players/player_id_here/battle_records使用PowerShell:
# 替换为实际的玩家ID
Invoke-RestMethod -Uri http://localhost:5000/api/players/player_id_here/battle_records -Method GET- 在Linux系统上运行时,API会绑定到0.0.0.0,允许从任何IP访问
- 密码使用bcrypt进行加密存储,确保安全性
- 首次运行时会自动创建数据存储文件
- 数据存储在JSON文件中,适合开发和测试环境,但不推荐用于生产环境
- 如果需要在生产环境使用,建议迁移到数据库存储(如PostgreSQL或MongoDB)