TypeError:无法读取 MEAN 堆栈中未定义的属性“_id”
Posted
技术标签:
【中文标题】TypeError:无法读取 MEAN 堆栈中未定义的属性“_id”【英文标题】:TypeError: Cannot read property '_id' of undefined in MEAN Stack 【发布时间】:2017-11-05 09:29:18 【问题描述】:我想要完成的是当用户发送消息时在数据库中写入消息。我正在使用带有 angular-cli 的 MEAN 堆栈。
我收到的错误是:
TypeError: Cannot read property '_id' of undefined
at JwtStrategy._verify (/Volumes/SSD/Documents/WebProjects/MEANTest/config/passport.js:11:38)
at /Volumes/SSD/Documents/WebProjects/MEANTest/node_modules/passport-jwt/lib/strategy.js:110:26
at /Volumes/SSD/Documents/WebProjects/MEANTest/node_modules/jsonwebtoken/verify.js:27:18
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
这是我用来查看是否有人能找出我做错了什么的所有代码。
Express 节点位于“/users”:
router.post('/newmessages', passport.authenticate('jwt', session: false), function(req, res, next)
var msgID = getMessageID(req.body.user.username);
let newMessage = Message(
createdBy:req.body.message.createdBy,
recipients:req.body.message.recipients,
dateCreated:getTodayDate(),
subject:req.body.message.subject,
message:req.body.message.message,
read: false,
previousMessage:req.body.message.previousMessage,
nextMessage:req.body.message.nextMessage,
messageID:msgID
);
console.log(newMessage);
Message.checkMessageID(newMessage, function(err, isFound)
if(err) throw err;
if(isFound)
newMessage.messageID = getMessageID(req.body.username);
else
Message.createMessage(newMessage, function(err, isCreated)
if(err) throw err;
if(isCreated)
var token = jwt.sign(req.body, config.secret,
expiresIn: 604800 // A week worth of seconds
);
res.json(
success: true,
token: "JWT " + token,
user:
id: req.body._id,
name: req.body.name,
username: req.body.username,
email: req.body.email
,
msg: "Your password has been changed."
);
else
var token = jwt.sign(req.body, config.secret,
expiresIn: 604800 // A week worth of seconds
);
res.json(
success: true,
token: "JWT " + token,
user:
id: req.body._id,
name: req.body.name,
username: req.body.username,
email: req.body.email
,
msg: "Your password has been changed."
);
);
);
);
PassportJS
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var User = require('../models/user');
var config = require('./database');
module.exports = function (passport)
let opts = ;
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done)
User.getUserByID(jwt_payload._doc._id, function(err, user)
if(err)
return done(err, false);
if(user)
return done(null, user);
else
return done(null, false);
);
));
;
Mongoose 架构和代码:
var mongoose = require('mongoose');
var config = require('../config/messages');
// Message Schema
var messageSchema = mongoose.Schema(
createdBy:
type: String,
required: true
,
recipients:
type: String,
required: true
,
dateCreated:
type: String,
required: true
,
subject:
type: String,
required: true
,
message:
type: String,
required: true
,
previousMessage:
type: String,
required: true
,
nextMessage:
type: String,
required: true
,
read:
type:Boolean,
required: true
,
messageID:
type: String,
required: true
);
var secondConn = mongoose.createConnection(config.database);
// On Connection
secondConn.on('connected', function()
console.log("Connected to database "+ config.database);
);
// On Error
secondConn.on('error', function(err)
console.log("Database Error " + err);
);
var Messages = module.exports = secondConn.model('Messages', messageSchema);
module.exports.getAllUserMessages = function(user, callback)
var query = createdBy: user;
Messages.find(query, callback);
;
module.exports.getAllRecpMessages = function(user, callback)
var query = recipients: user;
Messages.find(query, callback);
;
module.exports.deleteMessage = function(list, callback)
var query, i;
for(i = 0; i < list.length; i++)
query = messageID: list[i].messageID;
Messages.remove(query, function(err)
);
;
module.exports.createMessage = function(message, callback)
message.save(function(err, doc)
if(err) throw err;
if(doc === null)
callback(null, false);
else
callback(null, true);
);
;
// Returns false if no other message has the same ID
module.exports.checkMessageID = function(message, callback)
var query = messageID: message.messageID;
Messages.findOne(query, function(err, message)
if(err) throw err;
if(message === null)
callback(null, false);
else
callback(null, true);
);
;
'/users/messages' 的 Angular 打字稿:
import Component, OnInit from '@angular/core';
import AuthService from '../../services/auth.service';
import Router from '@angular/router';
import FlashMessagesService from 'angular2-flash-messages';
@Component(
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
)
export class MessagesComponent implements OnInit
createdBy: String;
recipients: String;
subject: String;
message: String;
previousMessage: String;
nextMessage: String;
user: Object;
constructor(private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
)
ngOnInit()
this.authService.getProfile().subscribe(profile =>
this.user = profile.user;
this.createdBy = profile.user.username;
,
err =>
console.log(err);
return false;
);
// Need to create Message object and pass to Back End
newMessage()
const newMessage =
createdBy: this.createdBy,
recipients: this.recipients,
subject: this.subject,
message: this.message,
previousMessage: " ",
nextMessage: " "
this.authService.newMessage(this.user, newMessage).subscribe(data =>
if(data.success)
this.authService.storeUserData(data.token, data.user);
console.log(data);
this.router.navigate(['profile']);
else
console.log(data);
this.router.navigate(['dashboard']);
);
getMessages()
this.authService.getMessages(this.user).subscribe(data =>
if(data.success)
this.authService.storeUserData(data.token, data.user);
this.router.navigate(['messages']);
console.log(data);
else
this.router.navigate(['dashboard']);
);
Angular 身份验证服务:
import Injectable from '@angular/core';
import Http, Headers from '@angular/http';
import 'rxjs/add/operator/map';
import tokenNotExpired from 'angular2-jwt';
@Injectable()
export class AuthService
authToken: any;
user: any;
message: any;
constructor(private http: Http)
// Need to pass Message object to Front End
newMessage(user, message)
console.log(user.username + " " + message.createdBy);
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
var info = user, message;
return this.http.post('/users/newmessages', user, headers: headers, body: info)
.map(res => res.json());
getMessages(user)
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.post('/users/messages', user, headers: headers)
.map(res => res.json());
registerUser(user)
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('/users/register', user, headers: headers)
.map(res => res.json());
authenticateUser(user)
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('/users/authenticate', user, headers: headers)
.map(res => res.json());
changePassword(user)
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.post('/users/changepassword', user, headers: headers)
.map(res => res.json());
getProfile()
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type', 'application/json');
return this.http.get('/users/profile', headers: headers)
.map(res => res.json());
storeUserData(token, user)
localStorage.setItem('id_token', token);
localStorage.setItem('user', JSON.stringify(user));
this.authToken = token;
this.user = user;
loadToken()
const token = localStorage.getItem('id_token');
this.authToken = token;
loggedIn()
return tokenNotExpired('id_token');
logout()
this.authToken = null;
this.user = null;
localStorage.clear();
以防万一,这是我来自 Mongoose Schema 的部分用户模型:
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var config = require('../config/database');
// User Schema
var userSchema = mongoose.Schema(
name:
type: String
,
email:
type: String,
required: true
,
username:
type: String,
required: true
,
password:
type: String,
required: true
,
verify:
type: Boolean,
required: true
);
【问题讨论】:
看起来错误可能是在您的 PassportJS 设置代码中抛出的以下行:User.getUserByID(jwt_payload._doc._id, function(err, user)...
。你能在那里console.log(jwt_payload)
确保它包含一个 _doc 键并且它包含一个 _id 键吗?
我在接受护照认证检查时忘记提到这适用于邮递员,但它从来没有从前到后工作过。
_doc
来自哪里?
@LeandroRodrigues 你是什么意思?
你的问题,似乎在这里:jwt_payload._doc._id
。 _doc
未定义。 _doc
值从何而来?
【参考方案1】:
哇,修好了!
在“/users/messages”的 Angular 打字稿中:
// Need to create Message object and pass to Back End
newMessage()
const newMessage =
createdBy: this.createdBy,
recipients: this.recipients,
subject: this.subject,
message: this.message,
previousMessage: " ",
nextMessage: " "
this.authService.newMessage(this.user, newMessage).subscribe(data =>
if(data.success)
this.authService.storeUserData(data.token, data.user); < Erased that line
console.log(data);
this.router.navigate(['profile']);
else
console.log(data);
this.router.navigate(['dashboard']);
);
TL;DR 解释,我传递了一个从后端提供的未定义的“数据”。我删除了标记的行以确保在发送消息后我没有存储用户数据......因为我不需要。
感谢所有帮助过我的人!
【讨论】:
【参考方案2】:我遇到了同样的问题
只需 console.log jwt_payload 即可查看 _id 在哪里
在我的代码中我有jwt_payload.data._id
删除 .data 对我的情况有所帮助
【讨论】:
很高兴我帮助了你以上是关于TypeError:无法读取 MEAN 堆栈中未定义的属性“_id”的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:无法读取 null 的属性“标题”!平均堆栈
Nodejs Promise TypeError:无法读取未定义的属性'then'
React JS,Firebase,TypeError:无法读取未定义的属性“initializeApp”