我已经看到了一个明确的例子,其中一个能力通过中间件存储在 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 函数。
这甚至可能吗?如果可以,你会怎么做?
感谢到目前为止。