jsonwebtoken

时间:2017-11-05 02:50:06

标签: javascript node.js angular jwt passport.js

我正在使用nodejs和angular cli创建一个Web应用程序 我正在使用JWT来验证我的登录功能。但是当我处理它时抛出了这个错误

  

错误:期望“有效负载”成为普通对象。       在验证时(D:\ Mean_Projects \ meanauthapp \ node_modules \ jsonwebtoken \ sign.js:34:11)       在validatePayload(D:\ Mean_Projects \ meanauthapp \ node_modules \ jsonwebtoken \ sign.js:56:10)       at Object.module.exports [as sign](D:\ Mean_Projects \ meanauthapp \ node_modules \ jsonwebtoken \ sign.js:108:7)       在User.comparePassword(D:\ Mean_Projects \ meanauthapp \ routes \ users.js:86:27)       在bcrypt.compare(D:\ Mean_Projects \ meanauthapp \ models \ user.js:53:9)       在D:\ Mean_Projects \ meanauthapp \ node_modules \ bcryptjs \ dist \ bcrypt.js:297:21       在D:\ Mean_Projects \ meanauthapp \ node_modules \ bcryptjs \ dist \ bcrypt.js:1353:21       在Immediate.next [as _onImmediate](D:\ Mean_Projects \ meanauthapp \ node_modules \ bcryptjs \ dist \ bcrypt.js:1233:21)       在runCallback(timers.js:785:20)       在tryOnImmediate(timers.js:747:5)       at processImmediate [as _immediateCallback](timers.js:718:5)

这是我的护照代码

    const JwtStrategy= require('passport-jwt').Strategy;
    const ExtractJwt=require('passport-jwt').ExtractJwt;
    const User= require('../models/user');
    const config=require('../config/database');        
    module.exports=function(passport){
    let opts={};
    opts.jwtFromRequest=ExtractJwt.fromAuthHeader();
    opts.secretOrKey=config.secret;
    opts.issuer = 'accounts.examplesoft.com';
    opts.audience = 'yoursite.net';
    passport.use(new JwtStrategy(opts,(jwt_payload,done)=>{
        console.log(jwt_payload);
        User.getUserById(jwt_payload._doc._id,(err,user)=>{
            if(err){
                return done(err,false);
            }
            if(user){
                return done(null,user);
            }
            else{
                return done(null,false);
            }
        });
    }));
}

我的身份验证和获取个人资料的代码

// Authenticate
router.post('/authenticate', (req, res, next) => {
  const username = req.body.username;
  const password = req.body.password;

  User.getUserByUsername(username, (err, user) => {
    if(err) throw err;
    if(!user){
      return res.json({success: false, msg: 'User not found'});
    }

    User.comparePassword(password, user.password, (err, isMatch) => {
      if(err) throw err;
      if(isMatch){
        const token = jwt.sign(user, config.secret, {
          expiresIn: 604800 // 1 week
        });

        res.json({
          success: true,
          token: 'JWT '+token,
          user: {
            id: user._id,
            name: user.name,
            username: user.username,
            email: user.email
          }
        });
      } else {
        return res.json({success: false, msg: 'Wrong password'});
      }
    });
  });
});

// Profile
router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res, next) => {
  res.json({user: req.user});
});

7 个答案:

答案 0 :(得分:75)

它在

行失败了
const token = jwt.sign(user, config.secret, {

错误“预期”有效负载“将成为普通对象”

您的user对象在此处初始化:

User.getUserByUsername(username, (err, user)

我假设它是mongoosejs对象,它包含许多方法并且不是“可序列化的”。您可以通过传递普通对象来处理此问题,方法是使用.lean()中的mongoose或普通toJSON方法:

const token = jwt.sign(user.toJSON(), config.secret, {
  expiresIn: 604800 // 1 week
});

答案 1 :(得分:13)

我也有这个问题,来自mongoose的返回用户,只需添加toJSON()toObject()即可解决问题,但如果您的用户并非总是来自mongoose会怎样?

你会得到一个

  

user.toJson / user.ToObject不是函数

如果您尝试在普通对象上执行此操作。

如果您的用户来自不同的来源并且您不知道它是否是普通对象,您可以这样解决:

JSON.parse(JSON.stringify(user));

答案 2 :(得分:3)

migration doc of passport-jwt

中明确提到了这一点

他们已从版本2和3中删除ExtractJwt.fromAuthHeader(),并使用新方法ExtractJwt.fromAuthHeaderAsBearerToken()或类似的方法代替旧方法。 for compelte reference visit

从日志中出现问题

User.comparePassword (D:\Mean_Projects\meanauthapp\routes\users.js:86:27) at 

所以这里需要在代码@every Bit

中更新四件事


首先在package.json文件中 使用*或版本号将版本更改为最新版本 通过转到项目目录并运行命令

  npm install passport-jwt --save
    "dependencies": {
    ....     
        "passport-jwt": "^3.0.1"
      }

或 写入文件并运行commadn

`npm install`
    "dependencies": {
        ....     
            "passport-jwt": "*"
          }

在验证方法

中再次更改此代码行
const token = jwt.sign(user.toJSON(), config.secret, {
  expiresIn: 604800 // 1 week
});

护照代码中的第三个更改旧方法

ExtractJwt.fromAuthHeader();

到新文档,您需要使用此方法opts.jwtFromRequest=ExtractJwt.fromAuthHeaderWithScheme('jwt');

并且第四次更改

User.getUserById(jwt_payload._id,(err,user)=>{

此解决方案适用于最新版本

  • 如果您仍想使用这种旧方法,那么


仅将package.json中passport-jwt的版本更改为1.xx(x是此处的nuber),选择较低版本然后2 ,移动到项目文件夹并运行命令npm install
你需要检查的唯一事情是payload_jwt中的数据,它将在第二层内,所以请检查jwt_payload。
好的,你已经准备好了,你已经处理好了User.getUserById(jwt_payload._doc._id,(err,user)=>{

答案 3 :(得分:1)

如果不是从月光来的 然后使用传播算子

const token = jwt.sign({ ...payload }, config.secret, {
  expiresIn: 100080
});

答案 4 :(得分:0)

这非常简单,如果用户来自数据库(mongo),则只需执行user.toJSON(),如果用户来自任何其他来源,则只需执行JSON.stringify(user)

答案 5 :(得分:0)

更改

const token = jwt.sign(user, config.secret, { expiresIn: 10080 });

收件人

const token = jwt.sign(user.toJSON(), config.secret, { expiresIn: 10080 });

答案 6 :(得分:0)

function utf8ize($mixed) {
    if (is_array($mixed)) {
        foreach ($mixed as $key => $value) {
            $mixed[$key] = utf8ize($value);
        }
    } else if (is_string ($mixed)) {
        return utf8_encode($mixed);
    } else if (is_object($mixed)) {
        $a = (array)$mixed; // from object to array
        return utf8ize($a);
    }
    return $mixed;
}

将其转换为

const token = jwt.sign(user, config.secret, {
      expiresIn: 604800 // 1 week
    });

或者您需要console.log(jwt_payload);查找您的ID位于_doc下或直接与jwt_payload在一起。因为这可能会随版本而改变。