Compare commits

...

2 Commits

Author SHA1 Message Date
293fbd8bc8 feat(server): 添加认证授权和日志记录功能
- 实现了 JWT 认证中间件,支持 token 验证和白名单路由
- 添加了登录接口,支持用户登录和 token 生成
- 集成了 log4js 日志系统,支持 mysql 和 koa 日志分类
- 配置了环境变量支持,添加了 SECRET_KEY 配置
- 重构了 MySQL 连接池配置,添加了查询日志记录
- 集成了 koa 路由和认证中间件,实现接口访问控制
2025-12-24 23:48:14 +08:00
18600b3015 feat(server): 重构服务端架构并集成MySQL数据库
- 添加MySQL数据库配置,包含主机地址、端口、用户名、密码和数据库名
- 创建独立的Koa服务器模块,包含路由配置和静态文件服务
- 实现MySQL连接池配置,支持命名占位符查询格式化
- 调整项目入口文件结构,分离MySQL和Koa服务模块
- 更新package.json配置,修改主入口文件并添加mysql2依赖
2025-12-24 22:27:36 +08:00
10 changed files with 143 additions and 34 deletions

1
module/server/.env Normal file
View File

@@ -0,0 +1 @@
SECRET_KEY=y7Y17cMV8fTzLTp

View File

@@ -1,3 +1,9 @@
export default { export default {
mysql: {
host: '192.168.25.110',
port: 3307,
user: 'root',
password: 'mysql_Adkijc',
database: 'mir_web'
}
} }

View File

@@ -1,29 +1,3 @@
import Koa from 'koa'; import "./mysql/index.js"
import Router from 'koa-router'; import "./koa/index.js"
import config from "./config/index.js" import "./log4js.js"
import koaStatic from 'koa-static';
const app = new Koa();
const router = new Router();
// 简单的路由示例
router.get('/', (ctx) => {
ctx.body = {message: 'Hello from Koa server!'};
});
router.get('/api/test', (ctx) => {
ctx.body = {message: 'This is a test API endpoint'};
});
router.get('/api/config', (ctx) => {
ctx.body = {data: config}
})
app.use(router.routes());
app.use(router.allowedMethods());
app.use(koaStatic('/www'))
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Koa server is running on port ${PORT}`);
});

26
module/server/koa/auth.js Normal file
View File

@@ -0,0 +1,26 @@
import jwt from "jsonwebtoken";
import * as log4js from "../log4js.js";
const whiteList = [
'/',
'/api/login',
]
async function auth(ctx, next) {
try {
log4js.koa.debug("接口请求:", ctx.path)
if (whiteList.includes(ctx.path)) {
await next();
return; // 终止后续验证逻辑
}
const token = ctx.request.headers.authorization?.split(' ')[1];
if (!token) throw new Error('无token');
ctx.user = jwt.verify(token, process.env.SECRET_KEY);
await next();
} catch (err) {
ctx.status = 401;
ctx.body = {msg: 'token无效或过期', code: 401};
}
}
export default auth;

View File

@@ -0,0 +1,31 @@
import Koa from 'koa';
import Router from 'koa-router';
import config from "../config/index.js"
import koaStatic from 'koa-static';
import registry from "./registry.js";
import * as log4js from "../log4js.js";
import auth from "./auth.js";
const app = new Koa();
const router = new Router();
// 简单的路由示例
router.get('/', (ctx) => {
ctx.body = {message: 'Hello from Koa server!'};
});
router.get('/api/config', (ctx) => {
ctx.body = {data: config}
})
app.use(auth)
app.use(router.routes());
app.use(registry)
app.use(router.allowedMethods());
app.use(koaStatic('/www'))
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
log4js.koa.info(`Koa server is running on port ${PORT}`);
});

View File

@@ -0,0 +1,24 @@
import Router from 'koa-router';
import mysql from "../mysql/index.js";
import jwt from "jsonwebtoken";
import * as log4js from "../log4js.js";
const router = new Router()
router.post("/api/login", async (ctx) => {
const {username, password} = ctx.request.body
if (['admin'].includes(username)) return ctx.body = {code: 1, message: "该账户不对外开放"}
const [rows] = await mysql.query("SELECT * FROM mir_web.player WHERE username = ? AND password = ?", [username, password])
if (rows?.length == 1) {
const token = jwt.sign(rows[0], process.env.SECRET_KEY, {expiresIn: '24h'});
return ctx.body = {code: 0, message: "登录成功", token}
}
log4js.koa.error("用户登录失败", username)
return ctx.body = {code: 1, message: "用户名或密码错误"}
})
router.post("/api/enter_game", async (ctx) => {
const {srvId, account} = ctx.request.body
})
export default router.routes()

View File

@@ -0,0 +1,5 @@
import Router from 'koa-router';
const router = new Router()
export default router.routes()

15
module/server/log4js.js Normal file
View File

@@ -0,0 +1,15 @@
import log4js from "log4js";
export const configure = {
appenders: {
console: {type: "console"},
},
categories: {
default: {appenders: ["console"], level: "ALL"},
},
}
log4js.configure(configure)
export const manager = log4js
export const mysql = log4js.getLogger("mysql")
export const koa = log4js.getLogger("koa")

View File

@@ -0,0 +1,24 @@
import mysql from "mysql2";
import config from "../config/index.js";
import * as log4js from "../log4js.js";
const pool = mysql.createPool({
host: config.mysql.host,
port: config.mysql.port,
user: config.mysql.user,
password: config.mysql.password,
connectionLimit: 10,
queryFormat: function (sql, values) {
const opts = { sql, values }
this._resolveNamedPlaceholders(opts)
log4js.mysql.debug(opts.sql, opts.values)
return mysql.format(
opts.sql,
opts.values,
this.config.stringifyObjects,
this.config.timezone
)
}
});
export default pool.promise();

View File

@@ -2,15 +2,18 @@
"name": "chuanqi-server", "name": "chuanqi-server",
"version": "1.0.0", "version": "1.0.0",
"description": "A simple Koa server for chuanqi web", "description": "A simple Koa server for chuanqi web",
"main": "index.js", "main": "koa/index.js",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "node index.js", "start": "node --env-file=.env index.js",
"dev": "nodemon index.js" "dev": "nodemon --exec \"node --env-file=.env\" index.js"
}, },
"dependencies": { "dependencies": {
"jsonwebtoken": "^9.0.3",
"koa": "^2.15.0", "koa": "^2.15.0",
"koa-router": "^12.0.0", "koa-router": "^12.0.0",
"koa-static": "^5.0.0" "koa-static": "^5.0.0",
"log4js": "^6.9.1",
"mysql2": "^3.16.0"
} }
} }