2016-02-17 28 views
7

Sto tentando di implementare la funzione di modifica password con il metodo integrato di Loopback, Funziona bene, ma non aggiorna la password con hash, ma semplicemente salva un testo in chiaro nel db. Sto usando il pacchetto loopback-component-passport npm in questo progetto. Ho cercato molti siti ma non riesco a trovare il modo corretto di implementare questa funzionalità. Qualcuno ha idea di come farlo?Implementare la password di modifica con Loopback

//Change user's pasword 
app.post('/change-password', function(req, res, next) { 
    var User = app.models.user; 
    if (!req.accessToken) return res.sendStatus(401); 
    //verify passwords match 
    if (!req.body.password || !req.body.confirmation || 
    req.body.password !== req.body.confirmation) { 
    return res.sendStatus(400, new Error('Passwords do not match')); 
    } 

    User.findById(req.accessToken.userId, function(err, user) { 
    if (err) return res.sendStatus(404); 
    user.hasPassword(req.body.oldPassword, function(err, isMatch) { 
     if (!isMatch) { 
     return res.sendStatus(401); 
     } else { 
     user.updateAttribute('password', req.body.password, function(err, user) { 
      if (err) return res.sendStatus(404); 
      console.log('> password change request processed successfully'); 
      res.status(200).json({msg: 'password change request processed successfully'}); 
     }); 
     } 
    }); 
    }); 
}); 

risposta

7

Usa built-in User.hashPassword, che vede nel codice sorgente

//Hash the plain password 
user.updateAttribute('password', User.hashPassword(req.body.password), function(err, user) { 
    ... 
}); 
+0

con questo ottengo 'TypeError: user.hashPassword non è una funzione 'cosa mi manca? –

+0

Ho usato 'User.hashPassword (req.body.password)' e ha funzionato come un fascino .. Grazie mille! –

+1

@VickyGonsalves sei il benvenuto, quando non riesci a capire qualcosa in loopback, controlla sempre il codice sorgente, aiuta molto –

4

Questo è in realtà un bug che è stato introdotto con il loopback-datasource-juggler 2.45.0. La password dovrebbe essere sottoposta a hash per impostazione predefinita.

https://github.com/strongloop/loopback-datasource-juggler/issues/844

https://github.com/strongloop/loopback/issues/2029

quindi attenzione se si utilizza user.hashpassword non può funzionare in una versione futura quando questo viene fissato dal momento che potrebbe hash un già-hash pw se non effettuate correttamente, ma ci dovrebbe già essere un controllo per la lunghezza più il controllo per $ 2 $ o qualunque sia il bit di inizio per i valori hash.

Modifica: Installare 2.45.1 di loopback-datasource-juggler e dovrebbe essere corretto.

+0

Grazie .. Non lo sapevo! –

1

Ecco la mia soluzione "completa" per implementare un metodo remoto updatePassword specifico in un progetto LoopBack/StrongLoop - IBM. Verificare che il pacchetto loopback-datasource-juggler abbia una versione superiore o uguale a 2.45.1 (npm list loopback-datasource-juggler). Il mio modello utente viene chiamato MyUserModel ed eredita dal modello integrato User:

"my-user-model.js"

module.exports = function (MyUserModel) { 

... 

MyUserModel.updatePassword = function (ctx, emailVerify, oldPassword, newPassword, cb) { 
    var newErrMsg, newErr; 
    try { 
    this.findOne({where: {id: ctx.req.accessToken.userId, email: emailVerify}}, function (err, user) { 
     if (err) { 
     cb(err); 
     } else if (!user) { 
     newErrMsg = "No match between provided current logged user and email"; 
     newErr = new Error(newErrMsg); 
     newErr.statusCode = 401; 
     newErr.code = 'LOGIN_FAILED_EMAIL'; 
     cb(newErr); 
     } else { 
     user.hasPassword(oldPassword, function (err, isMatch) { 
      if (isMatch) { 

      // TODO ...further verifications should be done here (e.g. non-empty new password, complex enough password etc.)... 

      user.updateAttributes({'password': newPassword}, function (err, instance) { 
       if (err) { 
       cb(err); 
       } else { 
       cb(null, true); 
       } 
      }); 
      } else { 
      newErrMsg = 'User specified wrong current password !'; 
      newErr = new Error(newErrMsg); 
      newErr.statusCode = 401; 
      newErr.code = 'LOGIN_FAILED_PWD'; 
      return cb(newErr); 
      } 
     }); 
     } 
    }); 
    } catch (err) { 
    logger.error(err); 
    cb(err); 
    } 
}; 

MyUserModel.remoteMethod(
    'updatePassword', 
    { 
    description: "Allows a logged user to change his/her password.", 
    http: {verb: 'put'}, 
    accepts: [ 
     {arg: 'ctx', type: 'object', http: {source: 'context'}}, 
     {arg: 'emailVerify', type: 'string', required: true, description: "The user email, just for verification"}, 
     {arg: 'oldPassword', type: 'string', required: true, description: "The user old password"}, 
     {arg: 'newPassword', type: 'string', required: true, description: "The user NEW password"} 
    ], 
    returns: {arg: 'passwordChange', type: 'boolean'} 
    } 
); 

... 
}; 

"my-user-model.json"

{ 
    "name": "MyUserModel", 
    "base": "User", 

    ... 

    "acls": [ 
    ... 
    { 
     "comment":"allow authenticated users to change their password", 
     "accessType": "EXECUTE", 
     "property":"updatePassword", 
     "principalType": "ROLE", 
     "principalId": "$authenticated", 
     "permission": "ALLOW" 
    } 
    ... 
    ], 
    ... 
} 

NB: The same functionality can be performed using a PUT request on MyUserModel and just specifying { "password":"...newpassword..."} in the body. But it probably is more convenient to have a specific remote method than this trick in order to enforce security policy on the new password.