挂钩以检查用户是否在 Feathers 中进行了身份验证(如果没有,则不发送未经授权的错误,只需检查)
Hook to check if user is authenticate in Feathers (without send Unauthorized error if not, just check)
我想为数据库中的文档实现一个简单的 "published" 字段。
例如,如果用户未通过身份验证,我想始终在所有 find/get 请求的查询中插入 { published: true },这样它将 return 仅发布文档(有用在前端)
但是如果用户通过身份验证并具有所需的角色,我想 return 所有文档,而不仅仅是发布(在管理员中有用)。
所以我正在尝试创建一个 before 挂钩:
// assignQuery.hook.js
const { some } = require('lodash');
const defaultOptions = {
rolesField: 'roles',
query: {},
allowRoles: []
};
module.exports = function (options) {
return async context => {
options = Object.assign({}, defaultOptions, options);
// If it was an internal call then skip this hook
if (!context.params.provider) {
return context;
}
const { user } = context.params;
// Return unchanged context if user have some "allowRoles"
if (user && options.allowRoles && options.allowRoles.length && some(options.allowRoles, (role) => {
return (user[options.rolesField] || '').includes(role);
})) return context;
// else assign query filter
context.params.query = Object.assign({}, context.params.query, options.query);
return context;
};
};
// service.hooks.js
module.exports = {
before: {
all: [],
find: [
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
],
get: [
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
],
create: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),
],
update: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),})
],
patch: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),
],
remove: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']})
]
},
};
问题是我必须对用户进行身份验证才能获得他的角色,因此如果用户未通过身份验证,服务将发送未经授权的错误,而不是允许使用过滤查询进行响应。
所以我必须在assignQuery 之前调用authenticate。在这种情况下,管理员可以正常工作,但前端未经授权的用户无法检索已发布的文章。
如果我在 assignQuery 之前不进行身份验证,它在前端工作正常,未经授权的用户只能看到已发布的文章,但它在管理员中不再工作,管理员也将始终只收到已发布的文章,因为在 assignQuery 挂钩中,context.params.user 未定义(因为我们之前没有进行身份验证...)
所以我需要一种方法来检查用户是否已通过身份验证,但如果他未经授权则不向他发送未授权错误,我只想发送修改后的查询的响应。
我想我需要这样的东西:
before: {
all: [],
find: [
unless(isAuthenticateAndHaveRoles({roles:['admin', 'edit']}),
assignQuery({ query: {published:true} })
)
],
...
但我不知道如何进行 "no-blocking" 身份验证或 isAuthenticate 挂钩。可能吗?
我希望我的解释不会那么混乱,目标只是为我的文档实现一个 published/draft (visible/hidden) (online/offline) 字段。
欢迎任何帮助。
非常感谢!
对于 Feathers v4 及更高版本,您可以使用 anonymous authentication 策略。
对于 v3 和更早版本,authenticate
挂钩有一个当前未记录的 allowUnauthenticated
选项,如果设置为 true
,则只会添加一个 params.authenticated
标志。所以
find: [
authenticate('jwt', {
allowUnauthenticated: true
}),
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
]
应该做。
我想为数据库中的文档实现一个简单的 "published" 字段。
例如,如果用户未通过身份验证,我想始终在所有 find/get 请求的查询中插入 { published: true },这样它将 return 仅发布文档(有用在前端)
但是如果用户通过身份验证并具有所需的角色,我想 return 所有文档,而不仅仅是发布(在管理员中有用)。
所以我正在尝试创建一个 before 挂钩:
// assignQuery.hook.js
const { some } = require('lodash');
const defaultOptions = {
rolesField: 'roles',
query: {},
allowRoles: []
};
module.exports = function (options) {
return async context => {
options = Object.assign({}, defaultOptions, options);
// If it was an internal call then skip this hook
if (!context.params.provider) {
return context;
}
const { user } = context.params;
// Return unchanged context if user have some "allowRoles"
if (user && options.allowRoles && options.allowRoles.length && some(options.allowRoles, (role) => {
return (user[options.rolesField] || '').includes(role);
})) return context;
// else assign query filter
context.params.query = Object.assign({}, context.params.query, options.query);
return context;
};
};
// service.hooks.js
module.exports = {
before: {
all: [],
find: [
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
],
get: [
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
],
create: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),
],
update: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),})
],
patch: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']}),
],
remove: [
authenticate('jwt'),
restrictToRoles({ roles: ['admin', 'edit']})
]
},
};
问题是我必须对用户进行身份验证才能获得他的角色,因此如果用户未通过身份验证,服务将发送未经授权的错误,而不是允许使用过滤查询进行响应。
所以我必须在assignQuery 之前调用authenticate。在这种情况下,管理员可以正常工作,但前端未经授权的用户无法检索已发布的文章。
如果我在 assignQuery 之前不进行身份验证,它在前端工作正常,未经授权的用户只能看到已发布的文章,但它在管理员中不再工作,管理员也将始终只收到已发布的文章,因为在 assignQuery 挂钩中,context.params.user 未定义(因为我们之前没有进行身份验证...)
所以我需要一种方法来检查用户是否已通过身份验证,但如果他未经授权则不向他发送未授权错误,我只想发送修改后的查询的响应。
我想我需要这样的东西:
before: {
all: [],
find: [
unless(isAuthenticateAndHaveRoles({roles:['admin', 'edit']}),
assignQuery({ query: {published:true} })
)
],
...
但我不知道如何进行 "no-blocking" 身份验证或 isAuthenticate 挂钩。可能吗?
我希望我的解释不会那么混乱,目标只是为我的文档实现一个 published/draft (visible/hidden) (online/offline) 字段。
欢迎任何帮助。 非常感谢!
对于 Feathers v4 及更高版本,您可以使用 anonymous authentication 策略。
对于 v3 和更早版本,authenticate
挂钩有一个当前未记录的 allowUnauthenticated
选项,如果设置为 true
,则只会添加一个 params.authenticated
标志。所以
find: [
authenticate('jwt', {
allowUnauthenticated: true
}),
assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
]
应该做。