SailsJS v1.0承载身份验证(API令牌)

时间:2019-02-03 13:26:46

标签: node.js rest sails.js passport.js bearer-token

首先,这不是重复的,因为那里的所有文档/答案都针对v1.0之前的版本,并且似乎不起作用。

我正在尝试使用passport和SailsJS v1.0实现简单的身份验证。

问题是...由于我是新手,并且sailsjs(v1)似乎缺少在线示例,因此我很受困扰。

应用程序应按以下方式工作->用户注册,验证其电子邮件,然后登录。登录后,用户会返回accessToken,他需要使用该Bearer来向受保护的路由发出请求(通过{{ 1}}或其他内容。

令牌应保存在数据库中,以便用户更改密码等时我可以使令牌无效。

我如何实现这样的目标?这就是我到目前为止(在线合并较旧/较新的示例)。

User.js(模型)

const bcrypt = require('bcryptjs');

module.exports = {
  attributes: {
    email: {
      type: 'string',
      required: true,
      unique: true
    },
    username: {
      type: 'string',
      required: true,
      unique: true
    },
    password: {
      type: 'string',
      required: true
    },
    tokens: {
      collection: 'token',
      via: 'userId'
    }
  },
  customToJSON: function () {
    return _.omit(this, ['password'])
  },
  beforeCreate: function (user, cb) {
    bcrypt.genSalt(10, function (err, salt) {
      bcrypt.hash(user.password, salt, null, function (err, hash) {
        if (err) return cb(err);
        user.password = hash;
        return cb();
      });
    });
  }
};

Token.js(模型)

module.exports = {

  attributes: {
    token: {
      type: 'string',
      required: true,
      unique: true
    },
    userId: {
      mode: 'user'
    },
    isValid: {
      type: 'bool',
    }
  },
};

由于我是Node的新手,尤其是帆,所以我有很多问题。

  1. 如果数据库中的令牌是,我如何在用户登录时创建令牌 无效(或者我应该在注册/更改时仅使用1个令牌) 密码?)
  2. 我如何实施实际的身份验证过程 使用passport吗?
  3. 令牌应为以下内容的特定格式(字符数等) 安全原因?
  4. 我要达到的目标是否有更好的方法? (成为 更确切地说,我想要一个REST Api后端来服务我的ReactJS前端 并能够将相同的后端重用于android / ios等)。

任何提示,链接,建议等将不胜感激。谢谢,请怜悯我缺乏知识!

编辑:这种方法会阻止我使用社交媒体登录吗(我也想在将来实现)?

1 个答案:

答案 0 :(得分:1)

您可以使用JWT进行身份验证。

使用以下代码在api / policies文件夹中创建名为isAuthenticated.js的文件。

const passport = require('passport');

module.exports = async (req, res, proceed) => {
  passport.authenticate('jwt', { session: false }, (err, user, info) => {
    if (err) {
      res.serverError(err, err.message);
    }
    if (user) {
      req.user = user;
      return proceed();
    }
    if (info) {
      return res.forbidden(info);
    }
    // Otherwise, this request did not come from a logged-in user.
    return res.forbidden();
  })(req, res, proceed);
};

使用jwt.js文件和以下代码在api文件夹中创建策略文件夹。

const JwtStrategy = require('passport-jwt').Strategy;
const { ExtractJwt } = require('passport-jwt');
const passport = require('passport');

const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = JWT_SECRET;
opts.issuer = JWT_ISSUER;
opts.audience = JWT_AUDIENCE;
opts.jsonWebTokenOptions = {
  expiresIn: JWT_EXPIRES_IN,
};

module.exports = {
  /**
   * Passport Strategy
   */
  passport: () => {
    passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
      User.findOne({ id: jwtPayload.id }, (err, user) => {
        if (err) {
          return done(err, null);
        }
        if (user) {
          return done(null, user);
        }
        return done({ message: 'No user account found' }, 'No user account found');
      });
    }));
  },
};

在文件顶部的app.js require('./api/strategies/jwt').passport();中。

现在,您可以将策略应用于config / policies.js中的路由。

要生成JWT,可以使用以下代码。

const jwt = require('jsonwebtoken');

module.exports = {
  generate: (id, email) => jwt.sign({ id, email }, jwtSecret, {
    audience: jwtAudience,
    expiresIn: jwtExpiresIn,
    issuer: jwtIssuer,
  })
};