feat(data_gateway/auth): 重构鉴权模块,新增权限控制中间件
- 新增IP标准化、请求IP获取、本地请求判断等工具函数 - 新增requireLocalOnly和requireInternalOnly权限中间件 - 将路由内的鉴权逻辑抽离为中间件,简化路由代码 - 更新模块与接口的注释描述 - 修复管理接口未授权访问的安全问题 - 优化内部查询接口权限,支持本地直连或内部token验证
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
// ============================================================
|
||||
// data_gateway/auth.js - 对外 API 鉴权模块
|
||||
// 职责:校验 X-API-Id + X-API-Key,匹配 skill config.json 中的哈希
|
||||
// data_gateway/auth.js - 数据网关鉴权与内网守卫模块
|
||||
// 职责:
|
||||
// - 校验 X-API-Id + X-API-Key
|
||||
// - 校验内部读取 token
|
||||
// - 统一提供 localOnly / internalOnly 语义
|
||||
// ============================================================
|
||||
const crypto = require('crypto')
|
||||
const fs = require('fs')
|
||||
@@ -45,6 +48,34 @@ const listEnabledSkills = () => {
|
||||
return result
|
||||
}
|
||||
|
||||
const normalizeIp = (value) => {
|
||||
const raw = String(value || '').trim()
|
||||
if (!raw) return ''
|
||||
if (raw.startsWith('::ffff:')) return raw.slice(7)
|
||||
return raw
|
||||
}
|
||||
|
||||
const getRequestIp = (req) => {
|
||||
const forwarded = String(req.headers['x-forwarded-for'] || '')
|
||||
.split(',')
|
||||
.map(item => normalizeIp(item))
|
||||
.find(Boolean)
|
||||
if (forwarded) return forwarded
|
||||
return normalizeIp(
|
||||
req.ip ||
|
||||
req.socket?.remoteAddress ||
|
||||
req.connection?.remoteAddress ||
|
||||
req.connection?.socket?.remoteAddress
|
||||
)
|
||||
}
|
||||
|
||||
const isLoopbackIp = (ip) => {
|
||||
const normalized = normalizeIp(ip)
|
||||
return normalized === '127.0.0.1' || normalized === '::1'
|
||||
}
|
||||
|
||||
const isLocalRequest = (req) => isLoopbackIp(getRequestIp(req))
|
||||
|
||||
// 校验外部 API 请求
|
||||
const verifyApiKey = (req) => {
|
||||
const apiId = String(req.headers['x-api-id'] || '').trim()
|
||||
@@ -82,4 +113,26 @@ const verifyInternalToken = (req) => {
|
||||
return { ok: true, skill: cfg }
|
||||
}
|
||||
|
||||
module.exports = { loadSkillConfig, refreshCache, listEnabledSkills, verifyApiKey, verifyInternalToken }
|
||||
const requireLocalOnly = (req, res, next) => {
|
||||
if (isLocalRequest(req)) return next()
|
||||
return res.status(403).json({ ok: false, error: 'local_only' })
|
||||
}
|
||||
|
||||
const requireInternalOnly = (req, res, next) => {
|
||||
if (isLocalRequest(req)) return next()
|
||||
const auth = verifyInternalToken(req)
|
||||
if (auth.ok) return next()
|
||||
return res.status(401).json({ ok: false, error: auth.error })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loadSkillConfig,
|
||||
refreshCache,
|
||||
listEnabledSkills,
|
||||
verifyApiKey,
|
||||
verifyInternalToken,
|
||||
getRequestIp,
|
||||
isLocalRequest,
|
||||
requireLocalOnly,
|
||||
requireInternalOnly
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user