循环引用阻止 jsonwebtoken.sign JSON.stringify 的原因

Posted

技术标签:

【中文标题】循环引用阻止 jsonwebtoken.sign JSON.stringify 的原因【英文标题】:Circular reference blocks jsonwebtoken.sign cause of JSON.stringify 【发布时间】:2017-03-20 03:28:06 【问题描述】:

我正在使用 Express 和 Sequelize 进行基于 upon this tutorial 的基本用户身份验证

当我想向用户签署令牌时,我收到一条错误消息,告诉我我正在尝试 JSON.stringify() 一个无法完成的循环引用。因此引发错误,我无法将令牌分配给用户。

当我在数据库中找到我的用户时,我做错了一个循环引用我只需要找到一个解决方案来打破我想的循环引用.哪位大神能解释一下是哪两个?

完整的错误是:

TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at toString (/Users/Desktop/express-jwt/node_modules/jws/lib/tostring.js:9:15)
    at jwsSecuredInput (/Users/Desktop/express-jwt/node_modules/jws/lib/sign-stream.js:12:34)
    at Object.jwsSign [as sign] (/Users/Desktop/express-jwt/node_modules/jws/lib/sign-stream.js:22:22)
    at Object.module.exports [as sign] (/Users/Desktop/express-jwt/node_modules/jsonwebtoken/sign.js:144:16)
    at Model.User.findOne.then.user (/Users/Desktop/express-jwt/server/index.js:69:27)
    at Model.tryCatcher (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/promise.js:510:31)
    at Promise._settlePromise (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/promise.js:567:18)
    at Promise._settlePromise0 (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/promise.js:612:10)
    at Promise._settlePromises (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/promise.js:691:18)
    at Async._drainQueue (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/async.js:138:16)
    at Async._drainQueues (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/async.js:148:10)
    at Immediate.Async.drainQueues (/Users/Desktop/express-jwt/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:574:20)
    at tryOnImmediate (timers.js:554:5)

我的服务器索引是:

const express = require(`express`);
const app = express();
const bodyParser = require(`body-parser`);
const morgan = require('morgan');

const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
const config = require('./config'); // get our config file
const db = require(`./models`);
const User = global.db.User;

const port = process.env.PORT || 8080;

db.sequelize.sync().then(() => 
    console.log(`Express server listening on port $port`);
);

app.set('superSecret', config.secret);

app.use(bodyParser.urlencoded(extended: false));
app.use(bodyParser.json());

app.use(morgan('dev'));

app.get('/', (req, res) => 
  res.send('Hello! The API is at http://localhost:' + port + '/api');
);

app.listen(port);
console.log('Magic happens at http://localhost:' + port);

app.get('/setup', (req, res) => 

  db.sequelize.sync().then(() => 
    return User.create(
      username: 'Kevin frafster',
      password: 'password',
      admin: true
    )
    .then(addedUser => 
      console.log(addedUser.get(
        plain: true
      ));
    )
    .catch(err => 
      res.json(err);
    );
  );

);

// API ROUTES -------------------

// get an instance of the router for api routes
const apiRoutes = express.Router();

apiRoutes.post('/authenticate', (req,res) => 
  User.findOne(
    where: username: req.body.username
  ).then(user => 
    if (!user) 
      res.json( success: false, message: 'Authentication failed. User not found.');
    else
      // console.log(user);
      if (user.password != req.body.password) 
        res.json( success: false, message: 'Authentication failed. Wrong password.' )
      else

        const token = jwt.sign(user, app.get('superSecret'), 
          expiresIn: 60*60*24
        );

        res.json(
          succes: true,
          message: 'Enjoy your token!',
          token
        );
      
    
  ).catch(err => 
    res.status(500).json(err);
  )
);

// TODO: route to authenticate a user (POST http://localhost:8080/api/authenticate)

// TODO: route middleware to verify a token

// route to show a random message (GET http://localhost:8080/api/)
apiRoutes.get('/', (req, res) => 
  res.json( message: 'Welcome to the coolest API on earth!' );
);

// route to return all users (GET http://localhost:8080/api/users)
apiRoutes.get('/users', (req, res) => 
  User.findAll()
    .then(users => 
      res.json(users);
    )
    .catch(err => 
      res.json(err);
    );
);

// apply the routes to our application with the prefix /api
app.use('/api', apiRoutes);

【问题讨论】:

【参考方案1】:

嗯,答案完全是花生。

1) 创建新对象并为其分配有效负载

const payload = username: user.username, password: user.password;

2) 使用新对象将令牌分配给

const token = jwt.sign(payload, app.get('superSecret'), 
  expiresIn: 60*60*24
);

【讨论】:

我不明白你的意思。哪个用户对象?你能解释一下你自己的解决方案吗?我遇到了同样的问题 谢谢。这拯救了我的一天

以上是关于循环引用阻止 jsonwebtoken.sign JSON.stringify 的原因的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:回调不是函数,“node_modules\jsonwebtoken\sign.js:101:14)”

阻止应用程序关闭

如何在Swift中识别出强大的参考周期?

为啥 Sleep() 函数会阻止整个循环工作?

如何阻止我的脚本循环

PHP循环阻止其余代码执行[关闭]