feathersjs授权定制问题

时间:2017-05-25 22:47:03

标签: rest jwt restful-authentication feathersjs express-jwt

我是使用feathersjs的新手,它非常灵活,对于简单的CRUD用例来说似乎非常高效。我一直在尝试定制羽毛的授权问题。自定义登录响应的文档中的示例显示在此处。

app.service('/authentication').hooks({
  after: {
    create: [
      hook => {
        hook.result.foo = 'bar';
      }
    ]
  }
});

按预期工作,收到的JSON具有访问令牌和foo属性。但是,如果我修改它,添加这样的钩子函数:

app.service('/authentication').hooks({
  after: {
    create: [
      hook => {
        hook.result.foo = 'bar';
      },
      login()
    ]
  }
});

或只是

after:{
  create: [ 
    login()
  ] ...

或者在之前设置它,没有设置新属性没关系。登录钩子代码是:

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) {
    // call a function that validates the username and password and returns a session id, rol and other information to fillout the payload
    const sequelizeClient = hook.app.get('sequelizeClient');
    sequelizeClient.query('SELECT ... ) // Sequelize magic
    .then(mySession => { // session successfully created
        hook.data.resultcode = mySession[0].resultcode;
        delete hook.data.usr;
        delete hook.data.pwd;
        //payload I want, but simply doesn't go or is partially taken
        var pload = { header: { typ: 'access' },
          strategy: 'jwt',
          'issuer': 'feathers',
          'subject': hook.data.resultcode.session_id,
          'audience': 'localhost',
          'rol': hook.data.resultcode.rol,
          'nbf': moment(),
          'iet': moment()
        };
        var opts = {
          name: 'jwt', 
          entity: 'sessions', 
          service: 'sessions',
          passReqToCallback: false, 
          session: false // whether to use sessions,
          //Verifier: Verifier
        };
        opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
          ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
          ExtractJwt.fromBodyField('body')
        ];
        opts.secret = 'secret';
        hook.data.payload = pload; // as documentation says to modify the payload, but does not work
        hook.params.payload = pload;
        hook.app.passport.createJWT(pload, opts)
        .then( jwtResult => {
          hook.result.token = jwtResult;
          console.log("after hook result:"+ JSON.stringify(hook.result));
          return hook;
        })
        .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');
    });
  };
};

此代码运行,会话在数据库中创建,一切正常,但响应在创建新令牌并在控制台中显示之前进入客户端。 foo在那里,但没有在hook.result对象中添加新的token属性。区别在于foo是同步添加的,token属性是异步设置的。我读了这个答案(Understanding FeathersJS hooks),但是对于使用feat-cli生成的代码,我不知道怎么做,如果它适用于Auk(我正在使用的羽毛版本)。现在我的问题:

  1. 如果异步生成令牌属性,我怎么能发送它?
  2. 如何更改/覆盖令牌的有效负载,密码和选项。事实上,秘密将是通过会话,而不是在配置中的唯一或系统范围。如果使用RSA加密令牌,系统范围可能会被设置为公钥。
  3. 如果资源是由REST服务器本身计算的,那么如何创建自定义服务(不基于sequelize,内存或其他后端)的示例是什么?在文档的高级部分中有一个示例会很好。
  4. 谢谢,对不起,如果答案很明显,但我还没有达到啊哈!第三个问题和第一个问题是关于案例的羽毛问题。

1 个答案:

答案 0 :(得分:0)

最后我能做到,我还回答了几天前发表的另一篇文章。

我创建了另一个名为session的服务,在服务创建代码中我把它放在:

module.exports = function () {
const app = this;

// Initialize our service with any options it requires
app.use('/v1/session', {
  create(data, params){
    console.log("creating service");
    const sequelizeClient = app.get('sequelizeClient');
    return sequelizeClient.query('SELECT ... //Sequelize magic must be returned its promise
    ).then(login => {
        delete data.usr;
        delete data.pwd;
        data.resultcode = login[0].resultcode;
        var payload = { 'iss': 'feathers',
          'sub': data.resultcode.session_id,
          'aud': 'localhost',
          'nbf': moment(),
          'iet': moment()
        };
        var opts = {
          name: 'jwt',
          entity: 'sessions',
          service: 'sessions',
          passReqToCallback: false,
          session: false
        };
        opts.jwtFromRequest = [ExtractJwt.fromAuthHeader(),
          ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
          ExtractJwt.fromBodyField('body')
        ];
        opts.secret = 'secret';
        return app.passport.createJWT(pload, opts) // Here is the correction return the nested promise
        .then( function(jwtResult) {
          delete data.resultcode;
          data.token = jwtResult;
          return Promise.resolve(data); // and return a promise with the desired result, which can be any object, not necessarily data or params
        })
        .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');
    });
  }
});

由于sequelize查询和createJWT函数的异步性质,响应始终是我在创建返回中设置的。因此,我意识到返回每个嵌套的promise(线索来自一个在身份验证示例中返回createJWT的示例),但我对sequelize的一个感到困惑。最后是处理羽毛承诺的新手错误。有了这个答案,我的other post也得到了答复。

感谢。