如何在Loopback的access钩子中获取req对象,实现全模型会话访问?
解决LoopBack
access钩子中无法获取ctx.req会话数据的问题 我之前也踩过这个坑!LoopBack的access钩子默认确实不会把HTTP请求的req对象直接放到上下文里——毕竟这个钩子不仅会在HTTP请求触发时运行,后台脚本直接调用模型方法也会触发,所以框架默认没绑定请求上下文。不过要让所有模型都能在access钩子里拿到会话数据,有两个实用的办法:
方法一:用loopback-context挂载请求上下文到钩子
这个是最直接的方案,通过LoopBack官方的上下文中间件把req对象传递到钩子上下文里:
- 先安装依赖包(如果还没装的话):
npm install loopback-context
- 修改
server/middleware.json,在session中间件之后添加loopback-context的配置,确保它能拿到会话数据:
{ "initial": { "session": { "express-session": { "params": { "secret": "mysceret", "saveUninitialized": true, "resave": true } } }, "loopback-context#per-request": { "params": { "injectOptions": { "req": true } } } } }
- 现在在任意模型的
access钩子里,就能通过ctx.get('req')拿到请求对象和会话了:
Post.observe('access', function(ctx, next) { const req = ctx.get('req'); // 要判断req是否存在,避免非HTTP场景报错 if (req && req.session?.user) { // 这里就可以根据会话设置查询过滤条件了 ctx.query.filter = ctx.query.filter || {}; ctx.query.filter.userId = req.session.user.id; } next(); });
方法二:创建全局基类统一处理
如果所有模型都需要这个逻辑,不如创建一个基类模型,让其他模型继承它,一次性搞定所有模型的会话逻辑:
- 在
common/models目录下新建base-model.js:
module.exports = function(BaseModel) { BaseModel.observe('access', function(ctx, next) { const loopbackContext = require('loopback-context').getCurrentContext(); const req = loopbackContext?.get('req'); if (req && req.session?.user) { // 这里可以写统一的过滤逻辑,比如强制筛选当前用户的数据 ctx.query.filter = { ...ctx.query.filter, userId: req.session.user.id }; } next(); }); };
- 在需要的模型(比如Post)的
post.json配置文件里,设置继承这个基类:
{ "name": "Post", "base": "BaseModel", // 其他模型配置... }
注意事项
- 一定要确保
loopback-context中间件在session中间件之后执行,不然会拿不到会话数据; - 非HTTP场景(比如用
node script.js调用模型方法)下req会是undefined,所以一定要加判断,避免代码报错; - 如果你的LoopBack版本是3.x,这个方案完全适用;如果是4.x的话,上下文机制略有不同,需要用
@inject来获取请求对象,但你的问题看起来是3.x版本,所以上面的方案没问题。
内容的提问来源于stack exchange,提问作者uday214125
相关产品推荐
相关产品推荐

