You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JsonWebToken时遇TypeError,无法获取用户数据求助

问题:JWT登录时获取用户数据失败,出现TypeError: Cannot read properties of null (reading '_id')

我在学习JsonWebToken基础时,用简洁代码实践。MongoDB里建了小数据库,文档包含_id、name、age、username字段。用Node.js写代码时,一直报错:TypeError: Cannot read properties of null (reading '_id')。如果移除payload里的userId,能拿到带令牌的响应,但data属性是null(即"data": {"doc": null})。我用Postman发POST请求,raw JSON格式,请求体输入{"username": "john25"}/{"username": "george15"}/{"username": "jim35"},地址是localhost:5000/login。相关代码如下:

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const app = express();

app.use(bodyParser.json());

const userSchema = new mongoose.Schema({
    name: { type: String, required: true },
    age: { type: Number, required: true },
    username: { type: String, required: true }, 
});

const User = mongoose.model('User', userSchema);

function login(req, res){
    const {username} = req.body;    
User.findOne({  username })
    .then(function(doc){ 
        const userId = doc._id;
        const token = jwt.sign({ userId }, 'abc123', {expiresIn: 250});
        return res.status(200).json({status: 'success', token, data: {doc}}); 
    });                     
}

app.post('/login', login);

mongoose.connect('mongodb+srv://username:password@cluster0.epwfttj.mongodb.net/?       retryWrites=true&w=majority')
.then(() => app.listen(5000))
.catch(err => console.log(err));

问题原因及解决办法

核心问题:查询不到匹配的用户文档

报错doc._id是因为User.findOne({username})返回了null,说明数据库里没有和请求体中username匹配的文档,可能的原因:

  • 集合名称不匹配:Mongoose默认会把模型名User转为小写复数形式的集合名(即users),如果你的数据库集合不是这个名字,需要在定义模型时指定集合名:const User = mongoose.model('User', userSchema, '你的集合名');
  • 用户名不一致:MongoDB查询默认区分大小写,确认请求里的username和数据库里的拼写、大小写完全一致
  • 数据库连接错误:当前连接字符串没有指定具体数据库,默认会连接test库,需要修改连接字符串为mongodb+srv://username:password@cluster0.epwfttj.mongodb.net/你的数据库名?retryWrites=true&w=majority,确保连接到存放用户数据的库

代码层面完善

必须处理查询结果为null的情况,避免报错,同时增加异常捕获:

function login(req, res){
    const {username} = req.body;    
    User.findOne({username})
        .then(function(doc){ 
            if (!doc) {
                return res.status(404).json({status: 'error', message: '用户不存在'});
            }
            const userId = doc._id;
            const token = jwt.sign({ userId }, 'abc123', {expiresIn: 250});
            return res.status(200).json({status: 'success', token, data: {doc}}); 
        })
        .catch(function(err) {
            return res.status(500).json({status: 'error', message: '服务器内部错误', error: err.message});
        });                     
}

额外建议

  • 不要把数据库密码、JWT密钥硬编码在代码里,用环境变量存储(比如process.env.MONGODB_URI、process.env.JWT_SECRET)
  • expiresIn: 250单位是秒,可根据实际需求调整过期时长

内容的提问来源于stack exchange,提问作者Miriyan Asenov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:37:10