express - 快速会话中的存储能力?
问题描述
我已经看到了一个明确的例子,其中一个能力通过中间件存储在 req 对象中。然后它使用以下方法来评估权限:
ForbiddenError.from(req.ability).throwUnlessCan('read', article);
我想实现类似的事情。我的想法是将能力保存在与 socket io websockets 共享的快速会话中。通过分享req.session
= socket.handshake.session
。我的方法如下,我从前端应用程序发出请求以获取规则以更新前端的能力。后端将能力保存在 express 会话中:
// abilities.js file
import { Ability } from '@casl/ability';
export const defineAbilitiesFor = (rules) => {
return new Ability(rules);
};
export default defineAbilitiesFor;
// handler for express route to get permissions from the frontend
export const getPermissions = async (req, res) => {
...
rules.push({
action: ['view'],
subject: views,
});
// manage all own processes
rules.push({
action: ['manage'],
subject: 'Process',
conditions: {
userId: req.kauth.grant.access_token.content.sub,
},
});
// store ability in session
req.session.rules = defineAbilitiesFor(rules);
const token = jwt.sign({ token: packRules(rules) }, 'secret');
if (token) {
return res.status(200).json(token);
} else {
return res.status(400).json('Error');
}
...
然后,当发生 websocket 请求时,我想在后端检查用户是否有权执行该操作:
ForbiddenError.from(socket.handshake.session.rules).throwUnlessCan('view', 'Process');
但是,这会引发以下错误:
TypeError: this.ability.relevantRuleFor is not a function
at ForbiddenError.throwUnlessCan
会话对象似乎具有正确的能力对象。当我 console.log socket.handshake.session.rules
,我得到以下输出:
{
h: false,
l: {},
p: {},
'$': [
{ action: [Array], subject: 'Process', conditions: [Object] },
{ action: [Array], subject: [Array] },
{ action: [Array], subject: 'Process', conditions: [Object] }
],
m: {}
}
罐头功能和我尝试的所有其他方法都不起作用。我认为将普通规则存储为会话中的对象,然后在每个请求起作用之前更新能力类,但我不想这样做。我想将能力存储在会话中,这样我只需要执行 throwUnlessCan 或 can 函数。
这甚至可能吗?如果可以,你会怎么做?
感谢到目前为止。
解决方案
无需存储整个Ability
实例,您只需存储其规则!rules 是一个普通的 js 对象数组,因此可以很容易地序列化。所以,将代码更改为:
export const getPermissions = async (req, res) => {
...
rules.push({
action: ['view'],
subject: views,
});
// manage all own processes
rules.push({
action: ['manage'],
subject: 'Process',
conditions: {
userId: req.kauth.grant.access_token.content.sub,
},
});
// store ability RULES in session
req.session.rules = rules;
const token = jwt.sign({
token: packRules(rules) // packRules accepts an array of RawRule! not an Ability instance
}, 'secret');
if (token) {
return res.status(200).json(token);
} else {
return res.status(400).json('Error');
}
要Ability
在其他处理程序中使用,请添加中间件:
function defineAbility(req, res, next) {
if (req.session.rules) {
req.ability = new Ability(req.session.rules);
next();
} else {
// handle case when there is no rules in session yet
}
}
// later
app.get('/api/users', defineAbility, (req, res) => {
req.ability.can(...);
// or
ForbiddenError.from(req.ability).throwUnlessCan(...);
})
推荐阅读
- unicode - 如何在记事本中强制 ANSI 编码
- python - 动态更改遗产树中的给定类并将其替换为另一个并初始化它
- javascript - Select2:无法创建超过 2 个字符的新选项(标签:true)
- xlsx - 我无法找到与我的 xml 文件有关的问题 如何在位置 0x001D4DA8 找到错误签名 (0x01549FF9)
- sparklyr - facebook Prophet 可以通过 spark_apply 应用于 sparklyr
- python - 如何在Django中获取字段的总和
- python - ```bash: xterm: command not found``` 运行 Python 时,Sublime Text 3 (Mac)
- dart - Flutter DatabaseException(唯一约束失败)
- node.js - 我们如何通过 typescript 获取 nodejs 中的 url 参数?
- autohotkey - Regexmach,结果存储 gui 编辑框