Come sapere se l'utente ha effettuato l'accesso con passport.js?


104

Ho letto passport.jsinformazioni e campioni per due giorni, ma non sono sicuro di aver eseguito tutto il processo di autenticazione.

Come faccio a sapere se sono loggato, ad esempio, avrò una barra di navigazione con un pulsante di login o logout, c'è qualche variabile come il codice qui sotto?

if (login)
   <button>logout</button>
else 
   <button>login</button>

Risposte:


210

Se l'utente ha effettuato l'accesso, passport.jscreerà un useroggetto reqper ogni richiesta in express.js, di cui è possibile verificare l'esistenza in qualsiasi middleware:

if (req.user) {
    // logged in
} else {
    // not logged in
}

Puoi creare un express.jsmiddleware semplice per questo, che controllerà se l'utente è connesso e, in caso contrario, reindirizzerà alla /loginpagina:

function loggedIn(req, res, next) {
    if (req.user) {
        next();
    } else {
        res.redirect('/login');
    }
}

E usalo:

app.get('/orders', loggedIn, function(req, res, next) {
    // req.user - will exist
    // load user orders and render them
});

È globale? Posso accedervi in ​​tutti i progetti dopo il login?
RMontes13

3
non è globale è solo sull'oggetto richiesta.
supernova

1
Nel 98,8% dello sviluppo web con express.js e passport.js gestirai le richieste (app.get, app.post, ecc.), Quindi parlare dell'utilizzo di passport.js al di fuori di esso è un po 'inutile. Sì, è solo all'interno di gestori di middleware per percorsi rapidi come app.get, app.postecc. Se hai bisogno di funzionalità diverse, dovresti spiegarlo in dettaglio nella tua domanda così come cosa stai cercando di ottenere.
moka

2
Ho scoperto che se non fornisco a router.get () alcun middleware per verificare l'autenticazione, come in "router.get ('/', my_controller.index)", passport non viene mai consultato e req.user lo farà sempre essere indefinito. Questo è frustrante perché desidero consentire a qualsiasi visitatore di chiamare un'API, ma adattare il contenuto della risposta a seconda di chi lo richiede.
Lawrence I. Siden

2
Qualcuno può spiegare come questo non sia sfruttabile? Quel controllo cerca semplicemente se il loro è un oggetto utente nella richiesta. Dov'è la convalida della sessione?
rambossa

46

Se desideri utilizzarlo nei tuoi modelli come sembra che il tuo esempio di codice indichi che puoi creare un middleware come questo:

app.use(function (req, res, next) {
  res.locals.login = req.isAuthenticated();
  next();
});

Inserisci quel codice da qualche parte dopo aver configurato il passaporto.

E poi usalo nel tuo modello (esempio di swig)

{% if login %}
<button>logout</button>
{% else %} 
<button>login</button>
{% endif %}

Per qualche motivo il middleware sopra mi dava un problema con l'utente non definito nel mio modello. Ho dovuto fornire nuovamente l'oggetto utente alla vista per risolverlo in questo modo: app.use(function(req,res,next){ res.locals.login = req.isAuthenticated(); res.locals.user = req.user; next(); });
Tebbers

Anche dopo un'autenticazione riuscita, isAuthenticatedrestituisce false nella richiesta successiva. Potresti aiutare a rispondere a questa domanda stackoverflow.com/questions/42842171/…
Suhail Gupta

3

Non è documentato esplicitamente ma esiste un isAuthenticated()metodo che viene inserito reqdal passaporto .
Può essere utilizzato come segue,

req.isAuthenticated() // returns true if auth, false if not

// auth.js
module.exports = {
  ensureAuthenticated: (req, res, next) => {
    if (req.isAuthenticated()) {
      return next()
    }
    res.redirect('/login') // if not auth
  },

  forwardAuthenticated: (req, res, next) => {
    if (!req.isAuthenticated()) {
      return next()
    }
    res.redirect('/dashboard');  // if auth    
  }
}

// app.js
app.get('/dashboard', ensureAuthenticated, (req, res) => res.render('dashboard'))
app.get('/login', forwardAuthenticated, (req, res) => res.render('login'))
app.get('/register', forwardAuthenticated, (req, res) => res.render('register'))

2

Stavo cercando una soluzione del genere e mi sono imbattuto in questa pagina. La domanda è come controllare lo stato di accesso sul lato client.

Dopo la registrazione nascondo il pulsante di accesso e mostro il pulsante di disconnessione. All'aggiornamento della pagina vedo di nuovo il pulsante di accesso invece del pulsante di disconnessione. L'unica soluzione è salvare un elemento in sessionStorage se stai usando session (e localStorage se stai usando JWT). Elimina questo elemento quando esci. Quindi in ogni caricamento della pagina controlla questo elemento sessionStorage e fai di conseguenza.

if (sessionStorage.getItem('status')) {
    $("#btnlogout").show();
    $("#btnlogin").hide();
// or what ever you want to do
} else {
    $("#btnlogout").hide();
    $("#btnlogin").show();
}



function Login() {
            var data = {
                username: $("#myModal #usr").val(),
                password: $("#myModal #pw").val()

            };
            $.ajax({
                type: 'POST',
                url: '/login',
                contentType: 'application/JSON; charset=utf-8',
                data: JSON.stringify(data),
                success: funcSuccess,
                error: funcFail
            });
            function funcSuccess(res) {
                sessionStorage.setItem('status', 'loggedIn');

                $("#btnlogout").show();
                $("#btnlogin").hide();
            }
            function funcFail() { $("#pp").text('Login Failed'); };
        };

function Logout() {
    $.ajax({
        type: 'GET',
        url: '/logout',
        contentType: 'application/JSON; charset=utf-8',
        success: funcSuccess,
        error: funcFail,
    });
    function funcSuccess(res) {
        $("#btnlogout").hide();
        $("#btnlogin").show();
        sessionStorage.removeItem("status");
    };
    function funcFail() { alert('Login method Failed'); };
}; 

2

usa il codice sottostante all'interno di app.get () o router.get ()

router.get('/edit/:id', (req, res)=>{
  if(req.isAuthenticated()){
     if(req.isAuthenticated()){
      //

      }
  else{
   res.redirect('/users/login');//your particular login routes
     }
});

0

Bella domanda, ho avuto alcuni problemi durante il tentativo di implementare qualcosa di simile, quando c'è una richiesta non autenticata il manubrio salta il blocco if se la variabile res.locals restituisce un valore falso. Per risolvere questo problema è necessario configurare un middleware nel file app.js per rendere req.user disponibile a livello globale nella tua app In questo modo ..

app.use(function (req, res, next) {
res.locals.login = req.user;
next();

});

Nel tuo file di intestazione puoi fare questo controllo per l'utente autenticato e visualizzare il contenuto in base in questo modo.

                {{#if login }}
                    <li><a href="#">User Account</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="#">Logout</a></li>
                {{/if}}
                {{#unless login}}
                    <li><a href="#">Sign up</a></li>
                    <li><a href="#">Sign in</a></li>
                {{/unless}} 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.