Fix dashboard symlink route + add auth rate limiting
- Add dashboard → docs/dashboard symlink in deploy workflow - Add rate limiting to auth/team-login endpoint (CodeQL fix) Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/3f62bf2e-92bd-44b5-b05e-b7bfe6772a4d
This commit is contained in:
parent
fba4088d7a
commit
cf362126cf
|
|
@ -252,6 +252,18 @@ jobs:
|
||||||
"${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
"${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
||||||
DP='${{ secrets.DEPLOY_PATH }}'
|
DP='${{ secrets.DEPLOY_PATH }}'
|
||||||
|
|
||||||
|
# dashboard → docs/dashboard(仪表盘在 docs/ 子目录下)
|
||||||
|
if [ -d \"\$DP/docs/dashboard\" ] && [ ! -e \"\$DP/dashboard\" ]; then
|
||||||
|
ln -s \"\$DP/docs/dashboard\" \"\$DP/dashboard\"
|
||||||
|
echo '✅ dashboard → docs/dashboard'
|
||||||
|
elif [ -L \"\$DP/dashboard\" ]; then
|
||||||
|
echo '✅ dashboard symlink 已存在'
|
||||||
|
elif [ -d \"\$DP/dashboard\" ]; then
|
||||||
|
echo '✅ dashboard 目录已存在'
|
||||||
|
else
|
||||||
|
echo '⚠️ docs/dashboard 不存在,跳过'
|
||||||
|
fi
|
||||||
|
|
||||||
# devboard → modules/devboard(开发者看板在 modules/ 子目录下)
|
# devboard → modules/devboard(开发者看板在 modules/ 子目录下)
|
||||||
if [ -d \"\$DP/modules/devboard\" ] && [ ! -e \"\$DP/devboard\" ]; then
|
if [ -d \"\$DP/modules/devboard\" ] && [ ! -e \"\$DP/devboard\" ]; then
|
||||||
ln -s \"\$DP/modules/devboard\" \"\$DP/devboard\"
|
ln -s \"\$DP/modules/devboard\" \"\$DP/devboard\"
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,25 @@ var TEAM_API_KEY = process.env.TEAM_API_KEY || '';
|
||||||
// 会话 token 签名密钥
|
// 会话 token 签名密钥
|
||||||
var SESSION_SECRET = process.env.SESSION_SECRET || crypto.randomBytes(32).toString('hex');
|
var SESSION_SECRET = process.env.SESSION_SECRET || crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
// 简易速率限制(防暴力枚举)
|
||||||
|
var loginAttempts = new Map();
|
||||||
|
var RATE_LIMIT_WINDOW_MS = 60 * 1000; // 1分钟窗口
|
||||||
|
var RATE_LIMIT_MAX = 10; // 每分钟最多10次
|
||||||
|
|
||||||
|
function checkRateLimit(ip) {
|
||||||
|
var now = Date.now();
|
||||||
|
var entry = loginAttempts.get(ip);
|
||||||
|
if (!entry || now - entry.windowStart > RATE_LIMIT_WINDOW_MS) {
|
||||||
|
loginAttempts.set(ip, { windowStart: now, count: 1 });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
entry.count++;
|
||||||
|
if (entry.count > RATE_LIMIT_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 开发者数据库(后续对接 Notion)
|
// 开发者数据库(后续对接 Notion)
|
||||||
var DEV_DATABASE = {
|
var DEV_DATABASE = {
|
||||||
'DEV-000': { name: '冰朔', level: 3, channel: 'system' },
|
'DEV-000': { name: '冰朔', level: 3, channel: 'system' },
|
||||||
|
|
@ -111,6 +130,15 @@ function requireSession(req, res, next) {
|
||||||
* 开发者编号免配置登录
|
* 开发者编号免配置登录
|
||||||
*/
|
*/
|
||||||
router.post('/auth/team-login', function(req, res) {
|
router.post('/auth/team-login', function(req, res) {
|
||||||
|
// 速率限制检查
|
||||||
|
var clientIp = req.ip || req.connection.remoteAddress || 'unknown';
|
||||||
|
if (!checkRateLimit(clientIp)) {
|
||||||
|
return res.status(429).json({
|
||||||
|
success: false,
|
||||||
|
message: '⚠️ 登录请求过于频繁,请稍后再试。'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var devId = (req.body.devId || '').trim().toUpperCase();
|
var devId = (req.body.devId || '').trim().toUpperCase();
|
||||||
|
|
||||||
if (!devId || !/^DEV-\d{3}$/.test(devId)) {
|
if (!devId || !/^DEV-\d{3}$/.test(devId)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue