Skip to content

cnlimiter/MineSkin

Repository files navigation

MineSkin (极速落地版起步实现)

基于 Project.MD 的“极速落地版”方案,已完成第一批后端落地:

  • Django + DRF 工程骨架;
  • Yggdrasil 核心端点:/api/yggdrasil/authenticate/api/yggdrasil/hasJoined
  • 游戏账号与令牌模型;
  • Django Admin 管理入口;
  • Docker 与 PostgreSQL/SQLite 双模式配置。
  • OIDC 登录/回调骨架(Authlib)。
  • authenticate/join/hasJoined 基础限流与审计日志。
  • 皮肤库(上传/浏览/绑定/解绑)与积分等级系统。

1. 本地开发

  1. 创建虚拟环境并安装依赖:
python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
  1. 配置环境变量:
cp .env.example .env

.env 里的 DB_ENGINE 改为 sqlite(本地无 PostgreSQL 时)。

  1. 迁移并启动:
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

2. Docker 启动

开发模式:

cp .env.example .env
docker compose up --build

生产模式(Gunicorn + Nginx):

cp .env.example .env
# 建议生产环境修改:
# DJANGO_DEBUG=false
# DB_ENGINE=postgres
mkdir -p logs/web logs/nginx
docker compose -f docker-compose.prod.yml up --build -d

生产模式说明:

  • Nginx 对外端口:80
  • 健康检查:GET /api/healthz
  • Gunicorn 日志:logs/web/access.loglogs/web/error.log
  • Nginx 日志:logs/nginx/access.loglogs/nginx/error.log

3. 前端启动(React + MUI)

cd frontend
npm install
npm run dev
  • 前端地址:http://127.0.0.1:5173
  • 开发环境默认通过 Vite Proxy 转发后端 API 到 http://127.0.0.1:8000
  • 如果后端不是本机地址,启动前可设置 VITE_API_BASE

4. 已实现接口

  • POST /api/yggdrasil/authenticate
    • 请求体示例:
{
  "username": "demo_user",
  "password": "demo_password_123",
  "profileId": "optional-profile-uuid-hex",
  "clientToken": "optional-client-token",
  "requestUser": true
}

说明:

  • 当携带 profileId 时,password 表示该游戏账号(profile)的“游戏口令”,用于多游戏账号登录。

  • 当不携带 profileId 时,走兼容模式:password 表示平台账号密码(旧客户端可继续使用)。

  • GET /api/yggdrasil/hasJoined?username=<name>&accessToken=<token>&clientToken=<optional>

  • GET /api/yggdrasil/hasJoined?username=<name>&serverId=<server-hash>

  • POST /api/yggdrasil/refresh

  • POST /api/yggdrasil/validate

  • POST /api/yggdrasil/invalidate

  • POST /api/yggdrasil/join

  • POST /api/yggdrasil/signout

  • GET /api/yggdrasil/publickey

  • GET /.well-known/yggdrasil.json

  • GET /api/healthz

  • GET /api/profiles/me

  • POST /api/profiles/me(创建游戏账号,返回一次性 gamePassword

  • GET /api/profiles/me/progress

  • GET /api/profiles/me/skins?sort=created|usage

  • PATCH /api/profiles/<uuid>(修改游戏名称)

  • POST /api/profiles/<uuid>/default(设为默认账号)

  • POST /api/profiles/<uuid>/enabled(启用/禁用账号)

  • POST /api/profiles/<uuid>/reset-password(重置游戏口令,返回一次性 gamePassword

  • POST /api/profiles/<uuid>/delete(删除账号,需要 {"confirm": true}

  • PATCH /api/profiles/<uuid>/textures

  • POST /api/profiles/<uuid>/bind-skin

  • POST /api/profiles/<uuid>/unbind-skin

  • POST /api/profiles/skins/upload(multipart)

  • GET /api/profiles/skins/library?scope=public|mine|all&sort=created|popular&search=<keyword>

  • PATCH /api/profiles/skins/<skinId>

  • DELETE /api/profiles/skins/<skinId>

  • POST /session/minecraft/join(sessionserver 兼容)

  • GET /session/minecraft/hasJoined?username=<name>&serverId=<server-hash>&ip=<optional>

  • GET /session/minecraft/profile/<uuid>?unsigned=<true|false>

  • POST /sessionserver/session/minecraft/join(legacy 兼容)

  • GET /sessionserver/session/minecraft/hasJoined?username=<name>&serverId=<server-hash>

  • GET /sessionserver/session/minecraft/profile/<uuid>

  • GET /api/oidc/login

  • GET /api/oidc/callback

  • POST /api/oidc/logout

  • GET /api/oidc/session

5. OIDC 配置

.env 中配置:

OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_SERVER_METADATA_URL=https://issuer.example.com/.well-known/openid-configuration
OIDC_SCOPE=openid profile email
OIDC_REDIRECT_URI=http://localhost:8000/api/oidc/callback
OIDC_FRONTEND_SUCCESS_URL=http://127.0.0.1:5173/auth/callback
OIDC_ALLOWED_REDIRECT_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
OIDC_AUTO_LINK_BY_EMAIL=true
OIDC_REQUIRE_VERIFIED_EMAIL=true
OIDC_AUTO_CREATE_USER=true
OIDC_LOGOUT_REDIRECT_URL=

安全相关可选配置:

RATE_YGG_AUTH=20/min
RATE_YGG_JOIN=120/min
RATE_YGG_HAS_JOINED=300/min
SECURITY_AUDIT_LOG_LEVEL=INFO
GAME_PASSWORD_FINGERPRINT_PEPPER=
YGGDRASIL_TEXTURES_KEYS_DIR=
YGGDRASIL_TEXTURES_ACTIVE_KEY_ID=default
YGGDRASIL_TEXTURES_PREVIOUS_KEY_IDS=

私钥轮换约定(推荐):

  1. 将各版本私钥按 <key_id>.pem 放到 YGGDRASIL_TEXTURES_KEYS_DIR
  2. YGGDRASIL_TEXTURES_ACTIVE_KEY_ID 切到新 key(例如 k2026)。
  3. 将旧 key id 写入 YGGDRASIL_TEXTURES_PREVIOUS_KEY_IDS(例如 k2025)作为过渡窗口。
  4. 通过 GET /api/yggdrasil/publickey 校验当前 keyIdpreviousPublicKeys 输出。

6. 下一阶段建议

  1. 协议一致性补齐
  • 继续对齐 Mojang/Yggdrasil 错误码与响应细节,补充边界场景(空参数、过期 join、错误 profile)。
  1. 皮肤库审核流程
  • 当前上传即入库;后续可增加“审核通过后发放上传积分”的审核状态流转。
  1. 3D预览引擎替换
  • 当前为轻量交互预览组件;如需更高拟真度,可替换为专用 Minecraft 皮肤渲染引擎。

Packages

No packages published

Languages