TypeError:无法读取属性' _id'在MEAN Stack

时间:2017-06-04 13:56:56

标签: javascript angularjs node.js express mongoose

我想要完成的是在用户发送消息时在数据库中编写消息。我正在使用带角度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);
    }
  });
};

&#39; / users / messages&#39;的角度打字稿:

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 auth服务:

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
  }
});

2 个答案:

答案 0 :(得分:3)

我遇到了同样的问题

只需console.log jwt_payload即可查看_id在哪里

在我的代码中,我有jwt_payload.data._id

删除.data对我的案子有帮助

答案 1 :(得分:2)

哇,修好了!

在&#39; / users / messages&#39;的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解释,我正在传递未定义的数据&#39;这是从后端给出的。我删除了标记的行,以确保我在发送消息后不存储用户数据...因为我不需要。

感谢所有帮助我的人!