security: 遗留清零——aiModel密钥永不下发/搜索正则注入转义/排行榜limit封顶且去openid/删除重复shop-items路由/登录入参强转防对象注入/sessionKey默认不返回
This commit is contained in:
+158
-158
@@ -1,158 +1,158 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { Admin, User } = require('../models')
|
||||
|
||||
/**
|
||||
* JWT 认证中间件(管理员)
|
||||
*/
|
||||
const authMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
// 从 header 获取 token
|
||||
const authHeader = req.header('Authorization')
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未提供认证令牌'
|
||||
})
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
|
||||
// 验证 token
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
|
||||
// 查找管理员
|
||||
const admin = await Admin.findById(decoded.adminId)
|
||||
if (!admin) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '管理员不存在'
|
||||
})
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
if (admin.status !== 'active') {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: '管理员账户已禁用'
|
||||
})
|
||||
}
|
||||
|
||||
// 将管理员信息附加到请求对象
|
||||
req.admin = admin
|
||||
next()
|
||||
} catch (error) {
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '无效的认证令牌'
|
||||
})
|
||||
}
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '认证令牌已过期'
|
||||
})
|
||||
}
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限检查中间件
|
||||
* @param {string} permission - 需要的权限
|
||||
*/
|
||||
const requirePermission = (permission) => {
|
||||
return (req, res, next) => {
|
||||
if (!req.admin) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未认证'
|
||||
})
|
||||
}
|
||||
|
||||
if (!req.admin.hasPermission(permission)) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: '权限不足'
|
||||
})
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序用户 JWT 认证中间件
|
||||
*/
|
||||
const userAuthMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
const authHeader = req.header('Authorization')
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未提供认证令牌'
|
||||
})
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
|
||||
// 兼容两种token格式:包含userId或openid
|
||||
let user = null
|
||||
if (decoded.userId) {
|
||||
user = await User.findById(decoded.userId)
|
||||
} else if (decoded.openid) {
|
||||
user = await User.findOne({ openid: decoded.openid })
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '用户不存在或令牌无效'
|
||||
})
|
||||
}
|
||||
|
||||
req.user = user
|
||||
// 优先使用 openid,如果没有则使用 userId 作为标识
|
||||
req.openid = user.openid || user._id.toString()
|
||||
next()
|
||||
} catch (error) {
|
||||
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '认证令牌无效或已过期'
|
||||
})
|
||||
}
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 可选的用户认证中间件(不强制要求登录)
|
||||
*/
|
||||
const optionalAuthMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
const authHeader = req.header('Authorization')
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
const user = await User.findById(decoded.userId)
|
||||
if (user) {
|
||||
req.user = user
|
||||
req.openid = user.openid
|
||||
}
|
||||
}
|
||||
next()
|
||||
} catch (error) {
|
||||
// 即使认证失败也继续,只是不附加用户信息
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
authMiddleware,
|
||||
requirePermission,
|
||||
userAuthMiddleware,
|
||||
optionalAuthMiddleware
|
||||
}
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { Admin, User } = require('../models')
|
||||
|
||||
/**
|
||||
* JWT 认证中间件(管理员)
|
||||
*/
|
||||
const authMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
// 从 header 获取 token
|
||||
const authHeader = req.header('Authorization')
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未提供认证令牌'
|
||||
})
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
|
||||
// 验证 token
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
|
||||
// 查找管理员
|
||||
const admin = await Admin.findById(decoded.adminId)
|
||||
if (!admin) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '管理员不存在'
|
||||
})
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
if (admin.status !== 'active') {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: '管理员账户已禁用'
|
||||
})
|
||||
}
|
||||
|
||||
// 将管理员信息附加到请求对象
|
||||
req.admin = admin
|
||||
next()
|
||||
} catch (error) {
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '无效的认证令牌'
|
||||
})
|
||||
}
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '认证令牌已过期'
|
||||
})
|
||||
}
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限检查中间件
|
||||
* @param {string} permission - 需要的权限
|
||||
*/
|
||||
const requirePermission = (permission) => {
|
||||
return (req, res, next) => {
|
||||
if (!req.admin) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未认证'
|
||||
})
|
||||
}
|
||||
|
||||
if (!req.admin.hasPermission(permission)) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: '权限不足'
|
||||
})
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序用户 JWT 认证中间件
|
||||
*/
|
||||
const userAuthMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
const authHeader = req.header('Authorization')
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '未提供认证令牌'
|
||||
})
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
|
||||
// 兼容两种token格式:包含userId或openid
|
||||
let user = null
|
||||
if (decoded.userId) {
|
||||
user = await User.findById(decoded.userId).select('+sessionKey') // vpay 签名需要
|
||||
} else if (decoded.openid) {
|
||||
user = await User.findOne({ openid: decoded.openid })
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '用户不存在或令牌无效'
|
||||
})
|
||||
}
|
||||
|
||||
req.user = user
|
||||
// 优先使用 openid,如果没有则使用 userId 作为标识
|
||||
req.openid = user.openid || user._id.toString()
|
||||
next()
|
||||
} catch (error) {
|
||||
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: '认证令牌无效或已过期'
|
||||
})
|
||||
}
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 可选的用户认证中间件(不强制要求登录)
|
||||
*/
|
||||
const optionalAuthMiddleware = async (req, res, next) => {
|
||||
try {
|
||||
const authHeader = req.header('Authorization')
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
const token = authHeader.replace('Bearer ', '')
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET)
|
||||
const user = await User.findById(decoded.userId)
|
||||
if (user) {
|
||||
req.user = user
|
||||
req.openid = user.openid
|
||||
}
|
||||
}
|
||||
next()
|
||||
} catch (error) {
|
||||
// 即使认证失败也继续,只是不附加用户信息
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
authMiddleware,
|
||||
requirePermission,
|
||||
userAuthMiddleware,
|
||||
optionalAuthMiddleware
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user