node.js - express-jwt 将用户对象设置为 req.user._doc 而不仅仅是 req.user?

标签 node.js mongodb express mongoose express-jwt

我过去使用 npm 包 express-jwt 来轻松进行 JWT 签名、解码等。通常(和 according to the docs )它会拦截请求,使用用户对象有效负载解码 token 并设置 req.user 到该有效负载。然而,这一次它显示 req.user 看起来像这样:

{ '$__': 
   { strictMode: true,
     getters: {},
     wasPopulated: false,
     activePaths: { paths: [Object], states: [Object], stateNames: [Object] },
     emitter: { domain: null, _events: {}, _maxListeners: 0 } },
  isNew: false,
  _doc: 
   { __v: 0,
     password: '$2a$10$ypbCbWsEA7W17IQjdox5Oe..MhhCco/0yIw.J1Y6m6vJDllCB0LLS',
     username: 'b',
     lastname: 'Last',
     firstname: 'First',
     _id: '56969210e3f8bf2ab9aee66d' },
  _pres: { '$__original_save': [ null, null, null ] },
  _posts: { '$__original_save': [] },
  iat: 1452709101 
}

不仅仅是:

{
    __v: 0,
    password: '$2a$10$ypbCbWsEA7W17IQjdox5Oe..MhhCco/0yIw.J1Y6m6vJDllCB0LLS',
    username: 'b',
    lastname: 'Last',
    firstname: 'First',
    _id: '56969210e3f8bf2ab9aee66d'
}

我试图弄清楚为什么这次我需要指定 req.user._doc 来获取有关用户的特定信息。我已经比较了每个来源的代码,它实际上与过去的项目相同,我只是并排测试它们 - 一个项目将 req.user 设置为用户对象,另一个将 req.user 设置为上面显示的对象,其中用户对象只能在 _doc 属性中找到。

我检查了两个项目中 mongoose .findOne() 方法实际返回的内容,它 两个项目中上面显示的较大对象,但表示- jwt 似乎在一个项目中自动清除了多余的东西,但在另一个项目中没有。

我还注意到,包含我不想要的所有附加信息的 JWT 比具有正确 req.user 对象的项目中的 JWT 长得多。所以也许这意味着当 JWT 使用有效负载签名时发生了一些奇怪的事情......

这是需要 req.user._doc 的相关代码:

server.js

...
var expressJwt = require('express-jwt');
var authRoutes = require('./routes/authRoutes');
var nationRoutes = require('./routes/nationRoutes');
...
app.use('/api', expressJwt({ secret: config.secret }));
app.use('/api/nation', nationRoutes);
app.use('/auth', authRoutes);
...

authRoutes.js

...
authRouter.post('/login', function (req, res) {
    User.findOne({ username: req.body.username }, function (err, user) {
        if (err) res.status(500).send(err);
        if (!user) res.status(401).send('The username you entered does not exist');
        else if (user) {
            bcrypt.compare(req.body.password, user.password, function (err, match) {
                if (err) throw (err);
                if (!match) res.status(401).send("Incorrect Password");
                else {
                    var token = jwt.sign(user, config.secret);
                    res.send({
                        user: user,
                        token: token
                    });
                }
            });
        }
    });
});
...

nationRoutes.js(问题正在显现)

此时,express-jwt 已经解码了 token 并(假设)设置了 token 的有效负载(应该只是用户的信息,而不是额外的 $__ 等内容)到 req.user,但我必须按照下面的代码所示执行 req.user._doc 才能使其工作。

...
nationRouter.route('/')
    .get(function (req, res) {
        console.log(req.user);  // Shows the larger object with added stuff from above
        Nation.find({ user: req.user._doc._id }, function (err, nations) {
            if (err) {
                res.status(500).send(err);
            }
            res.send(nations);
        });
    })
...

如果它有帮助,或者可能是问题的一部分,这里是用户模型和国家模型:

user.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require("bcrypt");

var userSchema = new Schema({
    firstname: {
        type: String,
        required: true
    },
    lastname: {
        type: String,
        required: true
    },
    username: {
        type: String,
        required: true,
        unique: true,
        lowercase: true
    },
    password: {
        type: String,
        required: true
    },
    email: String
});

userSchema.pre("save", function (next) {
    var user = this;

    if (!user.isModified("password")) {
        next();
    }

    bcrypt.hash(user.password, 10, function (err, hash) {
        if (err) return next(err);

        user.password = hash;
        next();
    }); 
});

module.exports = mongoose.model('User', userSchema);

nation.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var Nation = new Schema({
    name: {
        type: String,
        required: true
    },
    creationDate: {
        type: Date,
        default: Date.now
    },
    user: {
        type: Schema.Types.ObjectId,
        ref: 'User'
    }
});

module.exports = mongoose.model('Nation', Nation);

最佳答案

我在我的代码中使用了 jsonewebtoken 包的过去版本号,问题在版本 5.5.1 中消失了。 (5.5.2好像已经引入了这个问题)。我查看了 jsonwebtoken 的源代码,并在他们的 github 问题页面(herehere)上与一些开发人员进行了几次对话。似乎他们在 jwt.sign() 方法中向有效负载引入了一个名为 xtend 的包,这似乎是在编码之前将所有其他元属性添加到有效负载中.

我正在使用 Mongoose,根据一位 jsonwebtoken 开发人员的说法,我需要开始使用 Mongoose 的 Document.toObject() 方法。所以从现在开始:

...
jwt.sign(user.toObject(), ...)
...

将是在 Mongoose 中执行此操作的方式。

关于node.js - express-jwt 将用户对象设置为 req.user._doc 而不仅仅是 req.user?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34775687/

相关文章:

mysql - node-mysql中报SQL语法错误,查询在Sequel Pro中运行正常

javascript - 向 socket.io-client 客户端上的 self 发送事件

javascript - 无法连接到 dockerized postgresql 服务器

javascript - 从Javascript的每个函数中中断

javascript - 如何在 VueJS 中动态提供 API 发送的 pdf 文件?

node.js - 用于 SockJS + Express 的 Nodejs SSL

python - 创建一个可以增量更新的高效的基于文件的索引

python - 如何统计mongodb数组中的对象数量?

javascript - 在一个文件中要求express并在另一个文件中使用express.static

node.js - Mongoose 预删除有效,但不输出 Console.log