2016-04-15 44 views
6

Ze względów bezpieczeństwa tworzymy użytkowników i wysyłamy im tymczasowo wygenerowane hasło . Przy pierwszym logowaniu użytkownik powinien zmienić hasło przed kontynuowaniem nawigacji po chronionych stronach.Lokalne tymczasowe hasło do paszportu (zmiana przy pierwszym logowaniu)

Używam strony internetowej ekspresowej/węzłowej z modułem z lokalnym modułem. Rejestracja, logowanie w użytkownikach wszystkich prac. Ale jestem trochę zagubiony w sprawie najlepszych praktyk dla użytkowników, aby zmienić hasło przy pierwszym logowaniu.

Mój pomysł był aby wykonać następujące czynności:

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

Jak widać mam prostą logiczną (TINYINT 0-1) ustawić w mojej bazy danych (domyślnie 1). Później ustawię metodę post, która po udanej zmianie wartość boolowska zostanie ustawiona na 0.

Czy to jest poprawna metoda ("a", a nie "the": p)? A co z bezpieczeństwem?

Odpowiedz

4

Zdecydowanie jest to poprawna droga. Powiedziałbym, że idealnie pasuje do twoich potrzeb. Osobiście podoba mi się, w jaki sposób wykorzystanie twojego pola bazy danych bezpośrednio odzwierciedla logikę biznesową, która za tym stoi.

Alternatywy, choć jestem fanem rozwiązania, mogą być:

Dodawanie pola lastLogin datę do swojej bazy danych, która domyślnie do NULL. W ten sposób można zapisać znacznik datetime za każdym razem, gdy loguje się użytkownik. Możesz użyć go jako niejawnego czeku, jeśli użytkownik kiedykolwiek wcześniej się logował. Osobiście wolę mieć jawne kolumny do swoich celów (tak jak robisz to z kolumną firstLogin), ponieważ cel kolumny i logiki biznesowej aplikacji jest z tego bardzo jasny.

Inną alternatywą byłoby przechowywać, gdy użytkownik posiada ostatniej aktualizacji swojego hasła tj lastPasswordChange dotrzymującemu NULL dla nowych użytkowników. Takie samo rozumowanie jak powyżej. Może być przydatna, jeśli chcesz, aby użytkownicy zmieniali hasła co każde kolejne dni.

Mówiąc o bezpieczeństwie Powiedziałbym, że to będzie solidne. Dopóki twoje pole firstLogin domyślnie przyjmuje wartość 1, nie byłoby możliwości, aby nowy użytkownik mógł pominąć zmianę hasła przy pierwszym logowaniu.

Jednak, gdy użytkownik aktualizuje swoje hasło, należy zaktualizować pole firstLogin w tym samym zapytaniu lub wykonać oba zapytania wewnątrz transakcji. W ten sposób zawsze będziesz mieć pewność, że zmieniono zarówno hasło, jak i pole i.Jeśli z jakiegoś powodu zapytanie się nie powiedzie, będziesz mieć użytkownika, który już zmienił hasło i zostanie poproszony/zmuszony do zmiany go ponownie lub użytkownik, który ma losowo wygenerowane hasło, bez prośby o jego zmianę. Wykonanie tego wewnątrz tego samego zapytania spowoduje, że oba lub żadne z nich nie zostaną zaktualizowane w tym samym czasie. Wykonanie tej operacji w ramach transakcji pozostawia opcję niepowodzenia/wycofania transakcji, gdy którekolwiek z zapytań zakończy się niepowodzeniem.

Na innej notatki, kod może być napisany tak (zarówno swój sposób i to jest prawidłowe, to tylko kwestia preferencji i wizualny):

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

Jeśli chcesz bardziej konkretną odpowiedź aby zadać pytanie, potrzebowałbym bardziej konkretnego pytania.

+1

Przepraszamy za późną akceptację. Dziękuję za odpowiedź, bardzo mi pomogłeś. – Goowik

1

Prawdopodobnie dobrze jest przenieść logikę "sprawdź logowanie za pierwszym razem" w oddzielnym oprogramowaniu pośredniczącym, które wykonuje się dla wszystkich "zalogowanych tras".

Z powyższą sugestią użytkownik może po prostu przekierować/zmienić hasło po przekierowaniu?

+0

Nie mam nic przeciwko temu, aby użytkownik nawigował z dala od strony, ale gdy tylko będzie chciał się ponownie zalogować, zostanie ponownie poproszony o zmianę hasła. Prawdopodobnie zidentyfikuję całą sytuację, żeby to sprawdzić. – Goowik