2017-11-05 85 views
5

Robię aplikację internetową za pomocą nodejs i kanciastego cli Używam JWT do uwierzytelniania mojej funkcji logowania. Ale kiedy przetwarza je odrzucił ten błądBłąd ładowności w jsonwebtoken

Error: Expected "payload" to be a plain object. at validate (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:34:11) at validatePayload (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:56:10) at Object.module.exports [as sign] (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:108:7) at User.comparePassword (D:\Mean_Projects\meanauthapp\routes\users.js:86:27) at bcrypt.compare (D:\Mean_Projects\meanauthapp\models\user.js:53:9) at D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:297:21 at D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:1353:21 at Immediate.next [as _onImmediate] (D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:1233:21) at runCallback (timers.js:785:20) at tryOnImmediate (timers.js:747:5) at processImmediate [as _immediateCallback] (timers.js:718:5)

Oto mój kod paszport

const JwtStrategy= require('passport-jwt').Strategy; 
    const ExtractJwt=require('passport-jwt').ExtractJwt; 
    const User= require('../models/user'); 
    const config=require('../config/database');   
    module.exports=function(passport){ 
    let opts={}; 
    opts.jwtFromRequest=ExtractJwt.fromAuthHeader(); 
    opts.secretOrKey=config.secret; 
    opts.issuer = 'accounts.examplesoft.com'; 
    opts.audience = 'yoursite.net'; 
    passport.use(new JwtStrategy(opts,(jwt_payload,done)=>{ 
     console.log(jwt_payload); 
     User.getUserById(jwt_payload._doc._id,(err,user)=>{ 
      if(err){ 
       return done(err,false); 
      } 
      if(user){ 
       return done(null,user); 
      } 
      else{ 
       return done(null,false); 
      } 
     }); 
    })); 
} 

mojego kodu dla uwierzytelniania i uzyskać profil

// Authenticate 
router.post('/authenticate', (req, res, next) => { 
    const username = req.body.username; 
    const password = req.body.password; 

    User.getUserByUsername(username, (err, user) => { 
    if(err) throw err; 
    if(!user){ 
     return res.json({success: false, msg: 'User not found'}); 
    } 

    User.comparePassword(password, user.password, (err, isMatch) => { 
     if(err) throw err; 
     if(isMatch){ 
     const token = jwt.sign(user, config.secret, { 
      expiresIn: 604800 // 1 week 
     }); 

     res.json({ 
      success: true, 
      token: 'JWT '+token, 
      user: { 
      id: user._id, 
      name: user.name, 
      username: user.username, 
      email: user.email 
      } 
     }); 
     } else { 
     return res.json({success: false, msg: 'Wrong password'}); 
     } 
    }); 
    }); 
}); 

// Profile 
router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res, next) => { 
    res.json({user: req.user}); 
}); 

Odpowiedz

27

To nie na linii

const token = jwt.sign(user, config.secret, { 

z błędem „Oczekiwany«ładunek»być zwykły obiekt”

Twój user obiekt jest inicjowany tutaj:

User.getUserByUsername(username, (err, user) 

które zakładam jest mongoosejs obiekt, który zawiera wiele metod i nie "serializowalne". Można sobie z tym poradzić poprzez przepuszczenie zwykły przedmiot, przez każdą z wykorzystaniem .lean() z mongoose lub zwykły toJSON metody:

const token = jwt.sign(user.toJSON(), config.secret, { 
    expiresIn: 604800 // 1 week 
}); 
+0

Udało się! Dziękuję bardzo ! –

+0

@everyBit Cieszę się, że tak! Proszę "Zaakceptuj odpowiedź", jeśli nie masz nic przeciwko – Zilvinas

1

ten jest wyraźnie wymieniony w migration doc of passport-jwt

że usunięto ExtractJwt.fromAuthHeader() od wersji 2 i 3, a także do użycia nowej metody lub podobnej do tej w miejsce starej metody. dla compelte odniesienia visit

Od dzienniku nie jest kwestia

User.comparePassword (D:\Mean_Projects\meanauthapp\routes\users.js:86:27) at 

więc o cztery rzeczy muszą być aktualizowane w kodzie @every Bit


pierwsze w opakowaniu.plik json
zmienić wersję do najnowszej używając * lub wersja nie podoba Ci się to przechodząc do projektu katalogu i uruchomić polecenie

npm install passport-jwt --save 
    "dependencies": { 
    ....  
     "passport-jwt": "^3.0.1" 
     } 

lub zapisu w pliku i uruchom commadn

`npm install` 
    "dependencies": { 
     ....  
      "passport-jwt": "*" 
      } 

Po drugie zmień wiersz tego kodu w uwierzytelnionej metodzie

const token = jwt.sign(user.toJSON(), config.secret, { 
    expiresIn: 604800 // 1 week 
}); 

Trzecie miejsce e kod paszport zmienić starą metodę

ExtractJwt.fromAuthHeader(); 

do nowego, z odniesieniem doc trzeba użyć tej metody opts.jwtFromRequest=ExtractJwt.fromAuthHeaderWithScheme('jwt');

i czwarty to zmienić

User.getUserById(jwt_payload._id,(err,user)=>{ 

To rozwiązanie będzie działać na najnowsza wersja:


  • jeśli nadal chcesz korzystać z tej starej metody następnie


zmienić tylko wersję paszportu-JWT w package.json do 1.xx (x jest nuber tutaj) Twojego choise niższej wersji następnie 2,
przez przeniesienie do folderu projektu i runiczny polecenia npm install
jedyną rzeczą, którą należy sprawdzić jest dane w payload_jwt, to będzie wewnątrz drugiej warstwy tak, proszę sprawdzić jwt_payload.
ok masz wszystko ustawione, aby przejść trzeba było już obsługiwane User.getUserById(jwt_payload._doc._id,(err,user)=>{

0

miałem ten problem, a także, ze zwróconego użytkownika z mangusta, wystarczy dodać toJSON() lub toObject() będzie rozwiązać ten problem, ale co się stanie, jeśli użytkownik nie jest zawsze pochodzi z mangusty?

Dostaniesz

user.toJson/user.ToObject is not a function

jeśli starają się to zrobić na zwykłym przedmiotem.

Jeśli użytkownik pochodzi z różnych źródeł i nie wiem, czy będzie to zwykły przedmiot lub nie można go rozwiązać tak:

JSON.parse(JSON.stringify(user));