自定义身份验证策略¶
FeatusJS的Auk版本包括一个强大的新的 认证 建立在 PassportJS 之上.新插件非常灵活,允许您自定义几乎所有内容.我们可以利用它来使用 Passport Custom 创建完全自定义的身份验证策略.我们来看看本指南中的两个这样的例子.
设置基本应用程序¶
让我们首先创建一个基本的服务器设置.
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const auth = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');
const memory = require('feathers-memory');
const app = express(feathers());
app.configure(express.rest());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.configure(auth({ secret: 'secret' }));
app.configure(jwt());
app.use('/users', memory());
app.hooks({
before: {
all: [auth.hooks.authenticate('jwt')]
}
});
app.listen(8080);
创建自定义API密钥身份验证策略¶
我们可以看到的第一个自定义策略示例是API密钥策略.在其中,我们将检查请求中是否存在包含特定API密钥的特定标头.如果为true,我们将成功授权该请求.
First let’s make the strategy using passport-custom npm package.
const Strategy = require('passport-custom');
module.exports = opts => {
return function() {
const verifier = (req, done) => {
// get the key from the request header supplied in opts
const key = req.params.headers[opts.header];
// check if the key is in the allowed keys supplied in opts
const match = opts.allowedKeys.includes(key);
// user will default to false if no key is present
// and the authorization will fail
const user = match ? 'api' : match;
return done(null, user);
};
// register the strategy in the app.passport instance
this.passport.use('apiKey', new Strategy(verifier));
// Add options for the strategy
this.passport.options('apiKey', {});
};
};
接下来让我们将它添加到我们的服务器设置中
const apiKey = require('./apiKey');
app.configure(
apiKey({
// which header to look at
header: 'x-api-key',
// which keys are allowed
allowedKeys: ['opensesame']
})
);
接下来让我们创建一个自定义身份验证挂钩,有条件地为所有外部请求应用auth.
const commonHooks = require('feathers-hooks-common');
const authenticate = () =>
commonHooks.iff(
// if and only if the request is external
commonHooks.every(commonHooks.isProvider('external')),
commonHooks.iffElse(
// if the specific header is included
ctx => ctx.params.headers['x-api-key'],
// authentication with this strategy
auth.hooks.authenticate('apiKey'),
// else fallback on the jwt strategy
auth.hooks.authenticate(['jwt'])
)
);
app.hooks({
before: {
all: [authenticate()]
}
});
最后我们的 server.js 看起来像这样:
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const auth = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');
const memory = require('feathers-memory');
const commonHooks = require('feathers-hooks-common');
const apiKey = require('./apiKey');
const app = express(feathers());
app.configure(express.rest());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.configure(auth({ secret: 'secret' }));
app.configure(jwt());
app.configure(
apiKey({
header: 'x-api-key',
allowedKeys: ['opensesame']
})
);
app.use('/users', memory());
const authenticate = () =>
commonHooks.iff(
commonHooks.every(commonHooks.isProvider('external')),
commonHooks.iffElse(
ctx => ctx.params.headers['x-api-key'],
auth.hooks.authenticate('apiKey'),
auth.hooks.authenticate(['jwt'])
)
);
app.hooks({
before: {
all: [authenticate()]
}
});
app.listen(8080);
现在任何带有头文件 x-api-key 和值 opensesame 的请求都将由服务器验证.
创建匿名用户策略¶
我们将看到的第二个策略是匿名用户.对于这个特定的流程,我们希望客户端调用 /authentication 端点,让我们知道它想要匿名进行身份验证.然后,服务器将创建一个新用户并返回一个新的JWT令牌,客户端必须从该点开始使用该令牌.
首先让我们使用``passport-custom``创建策略
const Strategy = require('passport-custom');
module.exports = opts => {
return function() {
const verifier = async (req, done) => {
// create a new user in the user service
// mark this user with a specific anonymous=true attribute
const user = await this.service(opts.userService).create({
anonymous: true
});
// authenticate the request with this user
return done(null, user, {
userId: user.id
});
};
// register the strategy in the app.passport instance
this.passport.use('anonymous', new Strategy(verifier));
};
};
接下来让我们更新我们的 server.js 来使用这个策略.
const anonymous = require('./anonymous');
app.configure(
anonymous({
// the user service
userService: 'users'
})
);
const authenticate = () =>
commonHooks.iff(
commonHooks.every(commonHooks.isProvider('external')),
commonHooks.iffElse(
ctx => ctx.params.headers['x-api-key'],
auth.hooks.authenticate('apiKey'),
// add the additional anonymous strategy
auth.hooks.authenticate(['jwt', 'anonymous'])
)
);
最后我们的 server.js 看起来像这样:
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const auth = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');
const memory = require('feathers-memory');
const commonHooks = require('feathers-hooks-common');
const apiKey = require('./apiKey');
const anonymous = require('./anonymous');
const app = express(feathers());
app.configure(express.rest());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.configure(auth({ secret: 'secret' }));
app.configure(jwt());
app.configure(
apiKey({
header: 'x-api-key',
allowedKeys: ['opensesame']
})
);
app.configure(
anonymous({
userService: 'users'
})
);
app.use('/users', memory());
const authenticate = () =>
commonHooks.iff(
commonHooks.every(commonHooks.isProvider('external')),
commonHooks.iffElse(
ctx => ctx.params.headers['x-api-key'],
auth.hooks.authenticate('apiKey'),
auth.hooks.authenticate(['jwt', 'anonymous'])
)
);
app.hooks({
before: {
all: [authenticate()]
}
});
app.listen(8080);
现在任何此类请求都将返回有效的JWT令牌:
POST /authentication
{
strategy: 'anonymous'
}
注解
this looks very similar to a request body for local strategy:
POST /authentication
{
strategy: 'local',
username: 'admin',
password: 'password'
}
因此,对于我们注册的任何新策略,我们可以使用特定的主体调用 /authentication 端点并期望返回有效的JWT,我们可以在其上使用它.
我们可以看到使用 passport-custom 以标准护照方式创建完全自定义的身份验证策略非常容易.
快乐黑客!!