2016-04-15 31 views
6

Per motivi di sicurezza, creiamo utenti e inviamo loro una password generata temporanea . Al loro primo accesso l'utente dovrebbe cambiare la sua password prima di continuare a navigare nelle pagine protette.Password temporanea locale passaporto (modifica al primo accesso)

Utilizzo un sito Web express/node che esegue un modulo passaporto locale. Registrazione, accesso negli utenti tutto funziona. Ma mi sento un po 'perso sulle migliori pratiche per gli utenti di cambiare la loro password al primo accesso.

La mia idea era quella di effettuare le seguenti operazioni:

/* POST login page. */ 
router.post('/login', function(req, res, next) { 
    passport.authenticate('local', { successRedirect: '/dashboard/users', 
    failureRedirect: 'pages/login'}, function(err, user, info) { 
    if(err) { 
     console.log('') 
     return res.render('pages/login', {title: 'Login', error: err.message}); 
    } 

    if(!user) { 
     return res.render('pages/login', {title: 'Login', error: info.message}); 
    } 
    return req.logIn(user, function(err) { 
     if(err) { 
     return res.render('pages/login', {title: 'Login', error: err.message}); 
     } else if (user.firstLogin) { 
     return res.redirect('/change-password'); // <- First login 
     } else { 
     return res.redirect('/dashboard/users'); 
     } 
    }); 
    })(req, res, next); 
}); 

Come potete vedere ho un semplice booleano (tinyint 0-1) impostato nel mio database (default a 1). Successivamente imposterò un metodo di post che dopo una modifica avvenuta con successo, il booleano sarà impostato su 0.

È un modo corretto ('a' non 'il': p)? Che ne dici della sicurezza?

risposta

4

È sicuramente a modo corretto. Direi che si adatta perfettamente alle tue esigenze. Mi piace personalmente come l'utilizzo del campo del database rifletta direttamente la logica di business che sta dietro.

alternative, anche se sono fan della soluzione, potrebbe essere:

aggiunta di un campo lastLogin data per il database che il valore predefinito è NULL. Questo memorizzerebbe un timbro datetime ogni volta che l'utente si collega. Potresti usarlo come controllo implicito se l'utente ha mai effettuato l'accesso prima. Personalmente preferisco avere colonne esplicite per i loro scopi (come si sta facendo con la colonna firstLogin) perché lo scopo della colonna e della logica aziendale dell'applicazione è molto chiaro.

Un'altra alternativa potrebbe essere quella di memorizzare quando un utente ha aggiornato l'ultima volta la sua password cioè lastPasswordChange inadempiente per NULL per i nuovi utenti. Lo stesso ragionamento di cui sopra. Potrebbe essere utile se desideri che i tuoi utenti cambino le loro password ogni n giorni.

Parlando di sicurezza direi che questo è solido. Finché il campo firstLogin è impostato su 1, non è possibile che un nuovo utente possa saltare la modifica della password al primo accesso.

Tuttavia, quando un utente aggiorna la sua password, assicuratevi di aggiornare il campo firstLogin nella stessa query o eseguire entrambe le query all'interno di una transazione. In questo modo sarai sempre sicuro che sia la password e il campo firstLogin sono cambiati.Se per qualche ragione una query fallirebbe avresti un utente che ha già cambiato la password e viene chiesto/forzato di cambiarlo di nuovo o un utente che ha una password generata casualmente senza che gli venga chiesto di cambiarlo. Effettuarlo all'interno della stessa query assicurerebbe che entrambi, o nessuno dei due siano aggiornati allo stesso tempo. Farlo in una transazione ti lascia con l'opzione di fallire/rollback della transazione quando una query fallisce.

In un'altra nota, il codice potrebbe essere scritto in questo modo (sia la tua strada e questo è corretto, è solo una questione di preferenza e visivo):

/* POST login page. */ 
router.post('/login', function(req, res, next) { 
    passport.authenticate('local', { 
     successRedirect: '/dashboard/users', 
     failureRedirect: 'pages/login' 
    }, function(err, user, info) { 
     if(err) { 
      console.log('') 
      return res.render('pages/login', {title: 'Login', error: err.message}); 
     } 

     if(!user) { 
      return res.render('pages/login', {title: 'Login', error: info.message}); 
     } 
     return req.logIn(user, function(err) { 
      if(err) { 
       return res.render('pages/login', {title: 'Login', error: err.message}); 
      } 

      // Using if/else if/else makes no difference since if the first if is executed 
      // in both cases nothing else will execute due to if/else or the return. 
      // In case the above statement resolves to `false` the effect wills till be the same 

      if (user.firstLogin) { 
       return res.redirect('/change-password'); // <- First login 
      } 
      // The else is not necessary due to the return in the line above. 
      return res.redirect('/dashboard/users'); 
     }); 
    })(req, res, next); 
}); 

Se vuoi una risposta più specifica a entrambe le domande, avrei bisogno di una domanda più specifica.

+1

Ci scusiamo per l'accettazione tardiva. Grazie per la risposta, mi ha aiutato molto. – Goowik

1

Probabilmente è una buona cosa spostare la logica di "controllo del primo accesso" in un middleware separato che viene eseguito per tutti i "percorsi di accesso".

Con il tuo suggerimento sopra l'utente può semplicemente allontanarsi da/change-password dopo il reindirizzamento?

+0

Non mi dispiace che l'utente stia navigando lontano dalla pagina, ma non appena vuole effettuare nuovamente il login: gli verrà chiesto di nuovo di cambiare la sua password. Probabilmente registrerò l'intera situazione per verificarlo. – Goowik