feathersjs 无模式服务没有 return 预期的 JSON 对象
feathersjs modeless service does not return the expected JSON object
有人可以向我解释服务创建的工作原理吗?。经过几个小时撞墙收到 JSON 个对象,这不是我所期望的;我为 before 钩子提供了这段代码,它至少给了我一个 JSON 对象,而不是前一个的 404 错误。但是,正如我之前所描述的,无论在操作数据之前或之后使用什么挂钩,我放入服务创建函数中的任何内容都会返回。
服务代码现在是这个:
module.exports = function () {
const app = this;
// Initialize our service with any options it requires
app.use('/v1/login',{
create(data, params){
console.log("creating service");
return Promise.resolve(data); // data or params or whatever is returned to the REST ignoring any modification done via hooks
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('/v1/login');
service.hooks(hooks);
if (service.filter) {
service.filter(filters);
}
};
hooks 文件相同,after hook(登录)现在是这样的:
const errors = require('feathers-errors');
const jwt = require('feathers-authentication-jwt');
const ExtractJwt = require('passport-jwt').ExtractJwt;
const moment = require('moment');
module.exports = function () {
return function (hook) {
if (hook.type !== 'before') {
throw new errors.Unprocessable('This hook should only be used as before hook.');
}
const sequelizeClient = hook.app.get('sequelizeClient');
sequelizeClient.query('SELECT to_jsonb(login_user($app::varchar, $usr::varchar, $pwd::varchar)) resultcode',
{ bind: { app: hook.data.app, usr: hook.data.usr, pwd: hook.data.pwd },
type: sequelizeClient.QueryTypes.SELECT }
).then(login => {
if (login[0].resultcode.loginStatus !== 0){
throw new errors.NotAuthenticated(login[0].resultcode.message);
}else if(login[0].resultcode.sessionId !== null){
delete hook.data.usr;
delete hook.data.pwd;
hook.data.resultcode = login[0].resultcode;
var payload = { 'iss': 'feathers',
'sub': hook.data.resultcode.sessionId,
'aud': 'localhost',
'rol': hook.data.resultcode.rol,
'nbf': moment(),
'iet': moment(),
'jti': hook.data.resultcode.nonce
};
var opts = {
name: 'jwt',
entity: 'sessions',
service: 'sessions',
passReqToCallback: true,
session: false
};
opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
ExtractJwt.fromBodyField('body')
];
opts.secret = hook.data.resultcode.message;
hook.app.passport.createJWT(payload, opts)
.then( jwtResult => {
hook.result = { "token": jwtResult };
return hook;
})
.catch(error => {
console.log("JWT-ERROR: "+error);
throw new errors.GeneralError('Error generating jwt. Login failed');
});
}else{
console.log("ERROR: No session created");
throw new errors.GeneralError('Session cannot be created');
}
}).catch(error => {
console.log("ERROR: "+error);
throw new errors.GeneralError('Database error');
});
};
};
正如我所说,返回的是服务创建方法中接收到的参数。有没有办法摆脱服务创建的第二个参数?,我试过了,但随后出现了一个期望中间件功能的错误。我做错了什么或者我误解了钩子(我认为它们在返回 REST 客户端之前操纵数据和参数,但似乎不是那样。请解释。我是使用羽毛的新手.我本来希望能达到第161页写的"Pro Tip: hook.result Can also be set in a before hook which will skip the service method call (but run all other hooks).",但直到现在都没有运气。是否还有其他方法或条件我错过了?
更新,还没有运气
我看到了身份验证服务代码,我尝试做类似的事情,它们实际上 returns 创建令牌的 JWT promise 和 returns 内部的令牌 JSON,所以我把所有的过程都放在服务创建中(有或没有钩子都没有返回相同的结果
const errors = require('feathers-errors');
const jwt = require('feathers-authentication-jwt');
const ExtractJwt = require('passport-jwt').ExtractJwt;
const moment = require('moment');
const hooks = require('./login.hooks'); //optional the only hook on create is to validate that params user and password are present
const filters = require('./login.filters');
module.exports = function () {
const app = this;
// Initialize our service with any options it requires
app.use('/v1/login',{
create(data, params){
console.log("creating service");
const sequelizeClient = app.get('sequelizeClient');
var modelSession = sequelizeClient.query('SELECT to_jsonb(login_user($app::varchar, $usr::varchar, $pwd::varchar)) resultcode',
{ bind: { app: data.app, usr: data.usr, pwd: data.pwd, cte: params.headers },
type: sequelizeClient.QueryTypes.SELECT }
).then(login => {
if (login[0].resultcode.login_status !== 0){
throw new errors.NotAuthenticated(login[0].resultcode.pmessage);
}else if(login[0].resultcode.sessionId !== null){
delete data.usr;
delete data.pwd;
data.resultcode = login[0].resultcode;
var payload = { 'iss': 'feathers',
'sub': data.resultcode.sessionId,
'aud': 'localhost',
'rol': data.resultcode.rol,
'nbf': moment(),
'iet': moment(),
'jti': data.resultcode.nonce
};
var opts = {
name: 'jwt',
entity: 'sessions',
service: 'sessions',
passReqToCallback: false, // to avoid verification
session: false
};
opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
ExtractJwt.fromBodyField('body')
];
opts.secret = 'secret';
return app.passport.createJWT(pload, opts)
.then( function(jwtResult) { // mimic of authentication service, but less sophisticated
delete data.resultcode;
return { token: jwtResult }; // expected result, but nothing is received
})
.catch(error => {
console.log("JWT-ERROR: "+error);
throw new errors.GeneralError('Error generating jwt. Login failed');
});
}
}).catch(error => {
console.log("ERROR: "+error);
throw new errors.GeneralError('Database error');
});
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('/v1/login');
service.hooks(hooks); //This line can be commented out
if (service.filter) {
service.filter(filters);
}
};
钩子是这个
module.exports = {
before: {
all: [],
find: [ disallow() ],
get: [ disallow() ],
create: [ validateLoginParams() ], // just to see if the params are truthy
update: [ disallow(), disableMultiItemChange() ],
patch: [ disallow(), disableMultiItemChange() ],
remove: [ disallow(), disableMultiItemChange() ]
},
... //All is as in default, so empty brackets ;-)
}
项目是使用feathers-cli和feathers Auk创建的,这是相关包json
"dependencies": {
"body-parser": "^1.17.2",
"compression": "^1.6.2",
"cors": "^2.8.3",
"feathers": "^2.1.2",
"feathers-authentication": "^1.2.3",
"feathers-authentication-hooks": "^0.1.3",
"feathers-authentication-jwt": "^0.3.1",
"feathers-authentication-local": "^0.3.4",
"feathers-authentication-oauth2": "^0.2.4",
"feathers-configuration": "^0.4.1",
"feathers-errors": "^2.8.0",
"feathers-hooks": "^2.0.1",
"feathers-hooks-common": "^3.3.2",
"feathers-rest": "^1.7.2",
"feathers-sequelize": "^2.0.0",
"feathers-socketio": "^1.6.0",
"helmet": "^3.6.0", ...
我正在使用 feathersjs two/three 周,以开始一个新项目并且似乎是一个很好的 REST JavaScript 框架,我希望在未来的版本中看到它像 angular2 一样使用 TypeScript(对我来说更清晰的代码)。我希望尽快找到解决这个问题的方法,或者有人指出我犯了错误的地方,或者如果我确实不明白如何使用羽毛或它的用途。
仔细看了feathers中的认证码和其他服务是如何用sequelize创建的,才发现问题从一开始就是尝试做一个新的服务,不使用任何模型。我阅读了这两个用谷歌搜索的页面 https://github.com/feathersjs/feathers-hooks/issues/25 and https://github.com/feathersjs/feathers/issues/351,但是上述两个解决方案都导致了一个不存在的页面。真正的问题是如何做一个无模式的服务,或者说如何创建一个服务return一个不存在于任何后端的资源;换句话说,如何return一个通过服务生成的资源本身。
回答:没办法,除非您从头开始创建服务。也就是说,我唯一的方法是使用内置的身份验证服务,但是如果您需要做其他无模式的事情(不是身份验证,而是电子邮件注册,或者在服务中完成的过程或直接从数据库,但没有 CRUD),你必须询问 feathersjs 的开发人员,(请帮忙,我很快需要其他非 CRUD 服务)。
最后我只是去掉了default hook,修改后的认证服务代码是这样的:
// to create a new valid JWT (e.g. local or oauth2)
app.service('/v1/authentication').hooks({
before: {
create: [
// authentication.hooks.authenticate(config.strategies),
validateLoginParams(),
login()
],
remove: [
authentication.hooks.authenticate('jwt')
...
登录挂钩是 return 挂钩与结果的完整代码,我得到了访问令牌 JSON 。现在我的问题是生成的令牌没有我设置的有效负载,但只有那些在身份验证配置中不存在的部分。
感谢您花时间和耐心阅读这个代码故事。希望对其他新手有帮助。
有人可以向我解释服务创建的工作原理吗?。经过几个小时撞墙收到 JSON 个对象,这不是我所期望的;我为 before 钩子提供了这段代码,它至少给了我一个 JSON 对象,而不是前一个的 404 错误。但是,正如我之前所描述的,无论在操作数据之前或之后使用什么挂钩,我放入服务创建函数中的任何内容都会返回。
服务代码现在是这个:
module.exports = function () {
const app = this;
// Initialize our service with any options it requires
app.use('/v1/login',{
create(data, params){
console.log("creating service");
return Promise.resolve(data); // data or params or whatever is returned to the REST ignoring any modification done via hooks
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('/v1/login');
service.hooks(hooks);
if (service.filter) {
service.filter(filters);
}
};
hooks 文件相同,after hook(登录)现在是这样的:
const errors = require('feathers-errors');
const jwt = require('feathers-authentication-jwt');
const ExtractJwt = require('passport-jwt').ExtractJwt;
const moment = require('moment');
module.exports = function () {
return function (hook) {
if (hook.type !== 'before') {
throw new errors.Unprocessable('This hook should only be used as before hook.');
}
const sequelizeClient = hook.app.get('sequelizeClient');
sequelizeClient.query('SELECT to_jsonb(login_user($app::varchar, $usr::varchar, $pwd::varchar)) resultcode',
{ bind: { app: hook.data.app, usr: hook.data.usr, pwd: hook.data.pwd },
type: sequelizeClient.QueryTypes.SELECT }
).then(login => {
if (login[0].resultcode.loginStatus !== 0){
throw new errors.NotAuthenticated(login[0].resultcode.message);
}else if(login[0].resultcode.sessionId !== null){
delete hook.data.usr;
delete hook.data.pwd;
hook.data.resultcode = login[0].resultcode;
var payload = { 'iss': 'feathers',
'sub': hook.data.resultcode.sessionId,
'aud': 'localhost',
'rol': hook.data.resultcode.rol,
'nbf': moment(),
'iet': moment(),
'jti': hook.data.resultcode.nonce
};
var opts = {
name: 'jwt',
entity: 'sessions',
service: 'sessions',
passReqToCallback: true,
session: false
};
opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
ExtractJwt.fromBodyField('body')
];
opts.secret = hook.data.resultcode.message;
hook.app.passport.createJWT(payload, opts)
.then( jwtResult => {
hook.result = { "token": jwtResult };
return hook;
})
.catch(error => {
console.log("JWT-ERROR: "+error);
throw new errors.GeneralError('Error generating jwt. Login failed');
});
}else{
console.log("ERROR: No session created");
throw new errors.GeneralError('Session cannot be created');
}
}).catch(error => {
console.log("ERROR: "+error);
throw new errors.GeneralError('Database error');
});
};
};
正如我所说,返回的是服务创建方法中接收到的参数。有没有办法摆脱服务创建的第二个参数?,我试过了,但随后出现了一个期望中间件功能的错误。我做错了什么或者我误解了钩子(我认为它们在返回 REST 客户端之前操纵数据和参数,但似乎不是那样。请解释。我是使用羽毛的新手.我本来希望能达到第161页写的"Pro Tip: hook.result Can also be set in a before hook which will skip the service method call (but run all other hooks).",但直到现在都没有运气。是否还有其他方法或条件我错过了?
更新,还没有运气
我看到了身份验证服务代码,我尝试做类似的事情,它们实际上 returns 创建令牌的 JWT promise 和 returns 内部的令牌 JSON,所以我把所有的过程都放在服务创建中(有或没有钩子都没有返回相同的结果
const errors = require('feathers-errors');
const jwt = require('feathers-authentication-jwt');
const ExtractJwt = require('passport-jwt').ExtractJwt;
const moment = require('moment');
const hooks = require('./login.hooks'); //optional the only hook on create is to validate that params user and password are present
const filters = require('./login.filters');
module.exports = function () {
const app = this;
// Initialize our service with any options it requires
app.use('/v1/login',{
create(data, params){
console.log("creating service");
const sequelizeClient = app.get('sequelizeClient');
var modelSession = sequelizeClient.query('SELECT to_jsonb(login_user($app::varchar, $usr::varchar, $pwd::varchar)) resultcode',
{ bind: { app: data.app, usr: data.usr, pwd: data.pwd, cte: params.headers },
type: sequelizeClient.QueryTypes.SELECT }
).then(login => {
if (login[0].resultcode.login_status !== 0){
throw new errors.NotAuthenticated(login[0].resultcode.pmessage);
}else if(login[0].resultcode.sessionId !== null){
delete data.usr;
delete data.pwd;
data.resultcode = login[0].resultcode;
var payload = { 'iss': 'feathers',
'sub': data.resultcode.sessionId,
'aud': 'localhost',
'rol': data.resultcode.rol,
'nbf': moment(),
'iet': moment(),
'jti': data.resultcode.nonce
};
var opts = {
name: 'jwt',
entity: 'sessions',
service: 'sessions',
passReqToCallback: false, // to avoid verification
session: false
};
opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
ExtractJwt.fromBodyField('body')
];
opts.secret = 'secret';
return app.passport.createJWT(pload, opts)
.then( function(jwtResult) { // mimic of authentication service, but less sophisticated
delete data.resultcode;
return { token: jwtResult }; // expected result, but nothing is received
})
.catch(error => {
console.log("JWT-ERROR: "+error);
throw new errors.GeneralError('Error generating jwt. Login failed');
});
}
}).catch(error => {
console.log("ERROR: "+error);
throw new errors.GeneralError('Database error');
});
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('/v1/login');
service.hooks(hooks); //This line can be commented out
if (service.filter) {
service.filter(filters);
}
};
钩子是这个
module.exports = {
before: {
all: [],
find: [ disallow() ],
get: [ disallow() ],
create: [ validateLoginParams() ], // just to see if the params are truthy
update: [ disallow(), disableMultiItemChange() ],
patch: [ disallow(), disableMultiItemChange() ],
remove: [ disallow(), disableMultiItemChange() ]
},
... //All is as in default, so empty brackets ;-)
}
项目是使用feathers-cli和feathers Auk创建的,这是相关包json
"dependencies": {
"body-parser": "^1.17.2",
"compression": "^1.6.2",
"cors": "^2.8.3",
"feathers": "^2.1.2",
"feathers-authentication": "^1.2.3",
"feathers-authentication-hooks": "^0.1.3",
"feathers-authentication-jwt": "^0.3.1",
"feathers-authentication-local": "^0.3.4",
"feathers-authentication-oauth2": "^0.2.4",
"feathers-configuration": "^0.4.1",
"feathers-errors": "^2.8.0",
"feathers-hooks": "^2.0.1",
"feathers-hooks-common": "^3.3.2",
"feathers-rest": "^1.7.2",
"feathers-sequelize": "^2.0.0",
"feathers-socketio": "^1.6.0",
"helmet": "^3.6.0", ...
我正在使用 feathersjs two/three 周,以开始一个新项目并且似乎是一个很好的 REST JavaScript 框架,我希望在未来的版本中看到它像 angular2 一样使用 TypeScript(对我来说更清晰的代码)。我希望尽快找到解决这个问题的方法,或者有人指出我犯了错误的地方,或者如果我确实不明白如何使用羽毛或它的用途。
仔细看了feathers中的认证码和其他服务是如何用sequelize创建的,才发现问题从一开始就是尝试做一个新的服务,不使用任何模型。我阅读了这两个用谷歌搜索的页面 https://github.com/feathersjs/feathers-hooks/issues/25 and https://github.com/feathersjs/feathers/issues/351,但是上述两个解决方案都导致了一个不存在的页面。真正的问题是如何做一个无模式的服务,或者说如何创建一个服务return一个不存在于任何后端的资源;换句话说,如何return一个通过服务生成的资源本身。
回答:没办法,除非您从头开始创建服务。也就是说,我唯一的方法是使用内置的身份验证服务,但是如果您需要做其他无模式的事情(不是身份验证,而是电子邮件注册,或者在服务中完成的过程或直接从数据库,但没有 CRUD),你必须询问 feathersjs 的开发人员,(请帮忙,我很快需要其他非 CRUD 服务)。
最后我只是去掉了default hook,修改后的认证服务代码是这样的:
// to create a new valid JWT (e.g. local or oauth2)
app.service('/v1/authentication').hooks({
before: {
create: [
// authentication.hooks.authenticate(config.strategies),
validateLoginParams(),
login()
],
remove: [
authentication.hooks.authenticate('jwt')
...
登录挂钩是 return 挂钩与结果的完整代码,我得到了访问令牌 JSON 。现在我的问题是生成的令牌没有我设置的有效负载,但只有那些在身份验证配置中不存在的部分。
感谢您花时间和耐心阅读这个代码故事。希望对其他新手有帮助。