SailsJS v1.0 承载认证(API 令牌)

Posted

技术标签:

【中文标题】SailsJS v1.0 承载认证(API 令牌)【英文标题】:SailsJS v1.0 Bearer auth (API token) 【发布时间】:2019-06-27 10:31:12 【问题描述】:

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

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

问题是......因为我是新手,而且sailsjs (v1) 似乎缺乏在线示例,所以我很困惑。

应用程序应该像这样工作 -> 用户注册,验证他们的电子邮件,然后登录。登录后,用户会返回一个accessToken,他需要使用它来请求受保护的路线(通过Bearer 或别的东西)。

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

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

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',
    
  ,
;

由于我对节点非常陌生,尤其是风帆,我有很多问题。

    如果数据库中的令牌是 无效(或者我应该在注册/更改时只使用 1 个令牌 密码?) 如何实现实际的身份验证过程 使用passport ? 令牌是否应为特定格式(字符数等) 安全原因? 是否有更好的方法来实现我想要实现的目标? (成为 更确切地说,我想要一个 REST Api 后端来为我的 ReactJS 前端提供服务 能够为 android/ios 等重用相同的后端)。

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

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

【问题讨论】:

【参考方案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,
  )
;

【讨论】:

谢谢,但我宁愿使用存储在数据库中的令牌,我可以在我想要的任何时候使其失效。使用 JWT 不会让我使令牌失效,以防万一......假设用户更改了他的密码或类似的东西。 在这种情况下,最好使用基于会话的身份验证。 我的sailsjs 应用程序的整个想法是拥有一个rest api 后端并在React 中构建我的前端,然后在React Native 中添加移动应用程序。这就是为什么我试图将我的后端保持为独立而不是 MVC。

以上是关于SailsJS v1.0 承载认证(API 令牌)的主要内容,如果未能解决你的问题,请参考以下文章

OWIN 承载令牌认证

支持 JWT 密钥轮换的承载令牌认证的 Owin 中间件

zuul:不接受承载认证

Web Api中的JSON Web令牌与承载令牌

Web API 在 MVC 中存储承载令牌的位置

云视界API的授权承载令牌。