Passport.js kullanarak node.js'de kimlik doğrulamasından sonra önceki sayfaya yönlendirme


102

Node.js, express ve passport.js kullanarak bir giriş mekanizması kurmaya çalışıyorum. Oturum açmanın kendisi oldukça iyi çalışıyor, oturumlar da redis ile güzel bir şekilde saklanıyor, ancak kullanıcıyı kimlik doğrulaması istenmeden önce başladığı yere yönlendirmede bazı sorunlar yaşıyorum.

Örn: Kullanıcı takip bağlantısı http://localhost:3000/hiddendaha sonra yeniden yönlendirilir, http://localhost:3000/loginancak daha sonra tekrar yönlendirilmesini istiyorum http://localhost:3000/hidden.

Bunun amacı, eğer kullanıcı ilk olarak oturum açması gereken bir sayfaya rastgele erişirse, kimlik bilgilerini sağlayarak / login sitesine yönlendirilecek ve daha sonra daha önce erişmeye çalıştığı siteye yeniden yönlendirilecektir.

İşte giriş yazım

app.post('/login', function (req, res, next) {
    passport.authenticate('local', function (err, user, info) {
        if (err) {
            return next(err)
        } else if (!user) { 
            console.log('message: ' + info.message);
            return res.redirect('/login') 
        } else {
            req.logIn(user, function (err) {
                if (err) {
                    return next(err);
                }
                return next(); // <-? Is this line right?
            });
        }
    })(req, res, next);
});

ve burada sureAuthenticated Method'um var

function ensureAuthenticated (req, res, next) {
  if (req.isAuthenticated()) { 
      return next();
  }
  res.redirect('/login');
}

/hiddensayfaya bağlanan

app.get('/hidden', ensureAuthenticated, function(req, res){
    res.render('hidden', { title: 'hidden page' });
});

Giriş sitesi için html çıktısı oldukça basittir

<form method="post" action="/login">

  <div id="username">
    <label>Username:</label>
    <input type="text" value="bob" name="username">
  </div>

  <div id="password">
    <label>Password:</label>
    <input type="password" value="secret" name="password">
  </div>

  <div id="info"></div>
    <div id="submit">
    <input type="submit" value="submit">
  </div>

</form>

Merhaba Ben de aynısını yapıyorum, tek fark, kullanıcı başarıyla oturum açtığında, ardından "Hoş Geldiniz KullanıcıAdı" gibi bir mesajla welcome.html sayfasına yönlendireceğim. KullanıcıAdı'nın Oturum Açma Adı olacağını duyarsınız. Metin kutusu değerinin sonraki sayfaya nasıl geçirileceğini bana gösterebilir misiniz?
Dhrumil Şah

çok şey bilmiyordum sanırım basitçe geçip giderdim. Örneğime göre: res.render ('gizli', {başlık: 'gizli sayfa', kullanıcı adı: 'Tyrion Lannister'});
Alx

Yanıtlar:


84

Pasaport hakkında bir bilgim yok ama bunu nasıl yapıyorum:

Oturumda app.get('/account', auth.restrict, routes.account)bu setlerle kullandığım bir ara yazılımım var redirectTo... sonra / login adresine yönlendiriyorum

auth.restrict = function(req, res, next){
    if (!req.session.userid) {
        req.session.redirectTo = '/account';
        res.redirect('/login');
    } else {
        next();
    }
};

Sonra routes.login.postşunları yapıyorum:

var redirectTo = req.session.redirectTo || '/';
delete req.session.redirectTo;
// is authenticated ?
res.redirect(redirectTo);

cevabın için teşekkürler. Yönlendirmeyi / hesabı doğrudan kodunuzda ayarlamıyor musunuz? Başka bir bağlantınız varsa ne olur, diyelim ki aynı yetkilendirme kısıtlamasını kullanan / pro_accounts / hesaba yönlendirilecekler ....
Alx

4
Bu doğru. Giriş yaptıktan sonra her zaman / hesaba yönlendiriyorum, ancak bunureq.session.redirect_to = req.path
chovy

1
hm .. tam aradığım değil. Bir kullanıcının zaten yetkilendirilmiş olup olmadığını, yoksa / login adresine yönlendirilip yönlendirilmediğini anlamak için sureAuthenticated'i çağırıyorum. Bu görüşe göre / account'a geri dönmenin bir yolunu bulmalıyım. / Login içindeki req.path çağrısı bana basit / login geri veriyor. Yönlendiriciyi kullanmak da işe yaramaz, ayrıca tarayıcının yönlendireni doğru şekilde ayarlayıp ayarlamadığı tam olarak kesin değildir ...
Alx

6
req.session.redirect_to = req.pathKimlik doğrulama ara yazılımınızın içinde ayarlamanız gerekir . Ardından okuyun ve login.postrotada silin .
chovy

Bu, başarıyı kabul eden pasaport için harika bir çözüm değilRedirect, bir isteğin mevcut olmadığı bir noktada bir seçenek olarak
linuxdan

111

Senin içinde ensureAuthenticatedyöntemle böyle oturumda dönüş url kaydedin:

...
req.session.returnTo = req.originalUrl; 
res.redirect('/login');
...

Daha sonra passport.authenticate rotanızı aşağıdaki gibi güncelleyebilirsiniz:

app.get('/auth/google/return', passport.authenticate('google'), function(req, res) {
    res.redirect(req.session.returnTo || '/');
    delete req.session.returnTo;
}); 

7
İlk geçiş üzerinde çalıştım, ancak passport.authenticate rotasındaki yönlendirmeden sonra şunu eklemem gerekiyordu, sonraki çıkıştan / oturum açtıktan sonra returnTo adresine geri götürülmekten kaçınmak için: Pasaportun varsayılan çıkışıyla ilgili ek bilgi için bu soruyareq.session.returnTo = null; bakın. kaynak incelendiğinde, tüm oturumu değil, yalnızca session.user'ı temizlediği görülmektedir.
Rob Andren

Oturum yerine? callback = / profile gibi bir sorguyu kolayca iletebilir miyim
OMGPOP

@OMGPOP muhtemelen yapabilirdiniz, ancak bu pek güvenli gelmiyor, oturumdan yararlanmak istememenizin bir nedeni var mı?
linuxdan

@linuxdan hiç değil. ancak yönlendirme bağlantısını çıkarıp oturuma koymak zahmetli, ardından kullanıcı geri yönlendirdiğinde, oturumdaki yeniden yönlendirme bağlantısını geri atayın
OMGPOP

5
BaseUrl ve yolun bir kombinasyonu olduğu için req.pathkullanacağım yerine , dokümantasyonareq.originalUrl bakın
matthaeus


7

İşleri yapma şeklim:

const isAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    return next()
  }
  res.redirect( `/login?origin=${req.originalUrl}` )
};

GET / oturum açma denetleyicisi:

if( req.query.origin )
  req.session.returnTo = req.query.origin
else
  req.session.returnTo = req.header('Referer')

res.render('account/login')

POST / oturum açma denetleyicisi:

  let returnTo = '/'
  if (req.session.returnTo) {
    returnTo = req.session.returnTo
    delete req.session.returnTo
  }

  res.redirect(returnTo);

POST / oturum kapatma denetleyicisi (% 100 uygun olup olmadığından emin değilim, yorumlar kabul edilir):

req.logout();
res.redirect(req.header('Referer') || '/');
if (req.session.returnTo) {
  delete req.session.returnTo
}

ReturnTo ara yazılımını temizle (kimlik doğrulama rotaları dışında herhangi bir rotadaki oturumdan returnTo öğesini temizler - benim için bunlar / login ve / auth /: provider):

String.prototype.startsWith = function(needle)
{
  return(this.indexOf(needle) == 0)
}

app.use(function(req, res, next) {
  if ( !(req.path == '/login' || req.path.startsWith('/auth/')) && req.session.returnTo) {
    delete req.session.returnTo
  }
  next()
})

Bu yaklaşımın iki özelliği vardır :

  • bazı yolları isAuthenticated ara yazılım ile koruyabilirsiniz ;
  • herhangi bir sayfada giriş URL'sini tıklayabilir ve giriş yaptıktan sonra o sayfaya geri dönebilirsiniz ;

Burada o kadar çok iyi yanıt vardı ki, örneğinizi kullanabildim ve projemle çalışmasını sağladım. Teşekkür ederim!
user752746

5

Eğer kullanıyorsanız bağlantı-emin-giriş Pasaport kullanarak bunu yapmak için bir süper-kolay, entegre bir yolu vardır successReturnToOrRedirectparametreyi. Pasaport kullanıldığında, sizi başlangıçta istenen URL'ye veya sağladığınız URL'ye geri gönderecektir.

router.post('/login', passport.authenticate('local', {
  successReturnToOrRedirect: '/user/me',
  failureRedirect: '/user/login',
  failureFlash: true
}));

https://github.com/jaredhanson/connect-ensure-login#log-in-and-return-to


Bu, @ jaredhanson'un cevabının bir kopyası gibi görünüyor
mikemaccana

1

@chovy ve @linuxdan cevapları, kullanıcı giriş yönlendirmesinden sonra başka bir sayfaya giderse (bu kimlik doğrulama gerektirmez) ve oradan giriş yaparsa temizlememeyle ilgili bir hataya sahiptir session.returnTo. Bu kodu uygulamalarına ekleyin:

// clear session.returnTo if user goes to another page after redirect to login
app.use(function(req, res, next) {
    if (req.path != '/login' && req.session.returnTo) {
        delete req.session.returnTo
    }
    next()
})

Giriş sayfasından bazı ajax istekleri yaparsanız, bunları hariç tutabilirsiniz.


Başka bir yaklaşım da flaş kullanmaktır .ensureAuthenticated

req.flash('redirectTo', req.path)
res.redirect('/login')

Ve sonra GET girişinde

res.render('login', { redirectTo: req.flash('redirectTo') })

Görünümde oturum açma formuna gizli alan ekleyin (yeşimde örnek)

if (redirectTo != '')
    input(type="hidden" name="redirectTo" value="#{redirectTo}")

POST girişinde

res.redirect(req.body.redirectTo || '/')

RedirectTo'nun ilk GET oturum açtıktan sonra temizleneceğine dikkat edin.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.