使用混合身份验证创建端点¶
FeatusJS的Auk版本包括一个强大的新的 认证 建立在 PassportJS 之上.它可以自定义以处理几乎任何应用程序的身份验证要求.在本指南中,我们将介绍如何处理相当常见的身份验证方案:有时端点需要根据用户是否经过身份验证来提供不同的信息.未经身份验证的用户可能只会看到公共记录.经过身份验证的用户可能能够看到其他记录.
设置身份验证端点¶
首先,我们需要一个有效的身份验证设置.下面是默认配置和 authentication.js.它们包含由 feathers-cli 生成的相同代码.您可以使用以下终端命令创建以下设置:
npm install -g @feathersjs/climkdir feathers-demo-local; cd feathers-demo-local或您喜欢的文件夹名称.feathers generate app使用默认提示.feathers generate authentication提示输入提供商时,选择“用户名+密码(本地)”.
选择其余提示的默认值.
config/default.json:
{
"host": "localhost",
"port": 3030,
"public": "../public/",
"paginate": {
"default": 10,
"max": 50
},
"authentication": {
"secret": "99294186737032fedad37dc2e847912e1b9393f44a28101c986f6ba8b8bc0eaab48b5b4c5178f55164973c76f8f98f2523b860674f01c16a23239a2e7d7790ae9fa00b6de5cc0565e335c6f05f2e17fbee2e8ea0e82402959f1d58b2b2dc5272d09e0c1edf1d364e9911ecad8172bdc2d41381c9ab319de4979c243925c49165a9914471be0aa647896e981da5aec6801a6dccd1511da11b696d4f6cce3a4534dab9368661458a466661b1e12170ad21a4045ce1358138caf099fbc19e05532336b5626aa376bc158cf84c6a7e0e3dbbb3af666267c08de12217c9b55aea501e5c36011779ee9dd2e061d0523ddf71cb1d68f83ea5bb1299ca06003b77f0fc69",
"strategies": [
"jwt",
"local"
],
"path": "/authentication",
"service": "users",
"jwt": {
"header": {
"typ": "access"
},
"audience": "https://yourdomain.com",
"subject": "anonymous",
"issuer": "feathers",
"algorithm": "HS256",
"expiresIn": "1d"
},
"local": {
"entity": "user",
"service": "users",
"usernameField": "email",
"passwordField": "password"
}
},
"nedb": "../data"
}
src/authentication.js:
'use strict';
const authentication = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');
const local = require('@feathersjs/authentication-local');
module.exports = function () {
const app = this;
const config = app.get('authentication');
app.configure(authentication(config));
app.configure(jwt());
app.configure(local(config.local));
app.service('authentication').hooks({
before: {
create: [
authentication.hooks.authenticate(config.strategies)
],
remove: [
authentication.hooks.authenticate('jwt')
]
}
});
};
设置“混合验证”端点¶
现在我们需要设置一个端点来处理未经身份验证和经过身份验证的用户.对于此示例,我们将使用已由身份验证生成器创建的 /users 服务.假设我们的应用程序要求每个 user 记录都包含一个 public 布尔属性.每条记录看起来都像这样:
{
id: 1,
email: 'my@email.com'
password: "password",
public: true
}
如果 user 记录包含 public:true,则 未经身份验证的 用户应该能够访问它. 让我们看看如何使用来自 feathers-hooks-common 的 iff 和 else 条件钩子.实现这一目标. 一定要阅读 iff hook API docs 和 else hook API docs 如果你还没有.
只有在请求中有令牌时,我们才会使用 iff 钩子来验证用户身份. JWT身份验证.我们在 src/authentication.js 中使用的,包括一个令牌提取器.如果请求包含一个令牌,它将自动在 context.params.token 的 context 对象中可用.
src/services/users/users.hooks.js(这个例子只显示 find 方法的 before 钩子.)
'use strict';
const { authenticate } = require('@feathersjs/authentication').hooks;
const commonHooks = require('feathers-hooks-common');
module.exports = {
before: {
find: [
// If a token was included, authenticate it with the `jwt` strategy.
commonHooks.iff(
context => context.params.token,
authenticate('jwt')
// No token was found, so limit the query to include `public: true`
).else( context => Object.assign(context.params.query, { public: true }) )
]
}
};
让我们分解上面的例子.我们在钩子之前使用 iff 条件设置 /users 服务的 find 方法:
iff(
context => context.params.token,
authenticate(‘jwt’)
)
对于此应用程序,上面的代码段相当于下面的代码段.
context => {
if (context.params.token) {
return authenticate(‘jwt’)
} else {
return Promise.resolve(context)
}
}
iff 钩实际上比上面的简单演示更有能力.它可以处理异步谓词表达式.这相当于能够在 if 语句的括号内传递 promise.它还允许我们链接一个.else() 语句,如果谓词的计算结果为false,它将运行.
.else(
context => {
Object.assign(context.params.query, { public: true })
return context
)
上面的语句只是将 public:true 添加到查询参数中.这限制了查询只能找到 public 属性设置为 true 的 user 记录.
包起来¶
通过上面的代码,我们成功地设置了一个 /users 服务,该服务对未经身份验证和验证的用户做出不同的响应.我们使用 context.params.token 属性来验证用户或将搜索查询限制为仅限公共用户.如果您熟悉 Common Hooks API,您将能够解决几乎所有的身份验证难题.