如何实现基于用户名的期货资产访问及交易权限限制逻辑?
实现用户资产访问限制的解决方案
现有代码的核心问题
- 混淆了权限存储对象和查询函数:存储用户权限的是全局对象
userPermittedFutures,但在/futures接口中错误地对getPermittedFuturesAssets函数做属性判断,完全无法拿到正确的权限结果 - 异步逻辑未处理:
getPermittedFuturesAssets是异步数据库查询,原代码没有等待查询完成就直接返回结果,大概率会返回空权限 - 用户信息获取逻辑错误:
initializePassport.getCurrentUser()是全局调用,高并发场景下会出现用户信息串扰,express 框架中认证后的用户信息默认存储在req.user中 - 权限预加载逻辑缺失:没有主动触发
getPermittedFuturesAssets的调用,权限数据不会主动写入userPermittedFutures对象
具体实现步骤
1. 改造异步权限查询函数,支持async/await调用
改造后可以等待查询完成后再执行后续逻辑,避免返回空权限:
// 改造为async函数,支持等待查询完成 const getPermittedFuturesAssets = async (traderId) => { if (!pgClient) { await new Promise(resolve => setTimeout(resolve, 1000)); return getPermittedFuturesAssets(traderId); } const query = { name: 'fetch-futures-assets-permissions', text: 'SELECT trader_id, pair, pair_limit ' + 'FROM common.accounts_pairs_permits app ' + 'WHERE exists(SELECT * FROM future.instrument ap WHERE ap.symbol = app.pair) AND trader_id = $1', values: [traderId], }; try { const res = await pgClient.query(query); for (let row of res.rows) { addUserFuturesConstraints(row.trader_id, row.pair, row.pair_limit); } // 返回当前用户的权限列表 return userPermittedFutures[traderId] || {}; } catch (err) { console.error("Can't get account permitted futures permits. Retrying in a second..."); await new Promise(resolve => setTimeout(resolve, 1000)); return getPermittedFuturesAssets(traderId); } }
2. 修复/futures接口逻辑,仅返回用户有权限的资产
app.get('/futures', checkAuthenticated, async (req, res) => { try { // 从认证信息中取当前用户,避免全局串扰 const currentUser = req.user.username; const traderId = traderIdMnemonicMapping[currentUser]; if (!traderId) { return res.status(403).send({ status: 'fail', message: '未找到对应用户交易权限' }); } // 如果本地没有用户权限,先拉取权限 if (!userPermittedFutures[traderId]) { await getPermittedFuturesAssets(traderId); } // 直接取用户有权限的资产列表返回 const allowedFuturesAssetsForUser = Object.keys(userPermittedFutures[traderId] || {}); if (allowedFuturesAssetsForUser.length === 0) { console.log("Couldn't find Futures contracts for " + currentUser); return res.status(200).send([]); } res.status(200).send(allowedFuturesAssetsForUser); } catch (err) { console.log("Failed to get futures portfolios: " + err.message); res.status(503).send({ status: 'fail', message: err.message }); } });
3. 交易接口挂载权限校验中间件
你已经写好了isUserAbleToTradeFutures权限校验中间件,直接挂载到所有需要校验资产权限的交易接口上,就可以自动拦截无权限的交易请求:
// 示例:下单接口挂载权限校验中间件 app.post('/futures/order', checkAuthenticated, isUserAbleToTradeFutures, async (req, res) => { // 原有下单逻辑,走到这里的请求都已经通过权限校验 })
可选优化:简化资产权限判断逻辑
不需要遍历对象判断资产是否存在,直接判断对象key是否存在即可,性能更高:
function isFuturesAssetAllowedForUser(username, selectedFutureAsset) { const traderId = traderIdMnemonicMapping[username]; // 直接判断对象是否存在对应key即可,不需要遍历 return !!userPermittedFutures[traderId]?.[selectedFutureAsset]; }
你现有createUserFuturesAssetsConstraints函数的逻辑已经满足需求,不需要额外修改,它的作用是存储每个资产的交易上限,配合权限校验逻辑使用即可。
内容的提问来源于stack exchange,提问作者user1285928
相关产品推荐
相关产品推荐

