Programing

passport.js를 사용하여 node.js에서 인증 후 이전 페이지로 리디렉션

crosscheck 2020. 9. 1. 07:03
반응형

passport.js를 사용하여 node.js에서 인증 후 이전 페이지로 리디렉션


node.js, express 및 passport.js를 사용하여 로그인 메커니즘을 설정하려고합니다. 로그인 자체는 매우 훌륭하게 작동하고 세션도 redis로 잘 저장되지만 인증하라는 메시지가 표시되기 전에 사용자를 시작한 위치로 리디렉션하는 데 몇 가지 문제가 있습니다.

예를 들어 사용자는 링크 http://localhost:3000/hidden를 따라 리디렉션 http://localhost:3000/login되지만 다시 리디렉션되기를 원합니다 http://localhost:3000/hidden.

그 목적은 사용자가 먼저 로그인해야하는 페이지에 무작위로 액세스하는 경우 자신의 자격 증명을 제공하는 / login 사이트로 리디렉션 된 다음 이전에 액세스하려고 시도한 사이트로 다시 리디렉션되는 것입니다.

내 로그인 게시물입니다

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

그리고 여기에 내 ensureAuthenticated 메서드

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

/hidden페이지에 연결되는

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

로그인 사이트의 HTML 출력은 매우 간단합니다.

<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>

여권에 대해 잘 모르지만 방법은 다음과 같습니다.

세션에서 app.get('/account', auth.restrict, routes.account)해당 세트 와 함께 사용하는 미들웨어가 있습니다 redirectTo... 그런 다음 / login으로 리디렉션합니다.

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

그런 다음 다음을 routes.login.post수행합니다.

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

귀하의 ensureAuthenticated방법에서 다음과 같이 세션에 반환 URL을 저장하십시오.

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

그런 다음 passport.authenticate 경로를 다음과 같이 업데이트 할 수 있습니다.

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

원하는 것을 정확히 수행하기 위해 Passport와 함께 작동하는 connect-ensure-login을 살펴보십시오 !


당신이 사용하는 경우 연결 - 확인 - 로그인 여권은 사용하여이 작업을 수행 할 수있는 슈퍼 쉽게 통합 방법이 successReturnToOrRedirect매개 변수를. 패스포트를 사용하면 원래 요청 된 URL로 다시 보내거나 제공 한 URL로 대체됩니다.

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


My way of doing things:

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

GET /login controller:

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

res.render('account/login')

POST /login controller:

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

  res.redirect(returnTo);

POST /logout controller (not sure if there is 100% ok, comments are welcome):

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

Clear returnTo middleware (clears returnTo from session on any route except auth routes - for me they are /login and /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()
})

This approach have two features:

  • you can protect some routes with isAuthenticated middleware;
  • on any page you can simply click on login URL, and after login return to that page;

@chovy and @linuxdan answers have bug with not clearing session.returnTo if user goes to another page after login redirect (thats doesn't require authentication) and logins through there. So add this code to their implementations:

// 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()
})

If you do some ajax requests from login page, you can also exclude them.


Another approach is to use flash in ensureAuthenticated

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

And then in GET login

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

In view add hidden field to login form (example in jade)

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

In POST login

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

Notice that redirectTo will clear after first GET login with it.


Easiest (and properly) way to achieve this is setting failureRedirect and successRedirect options.

참고URL : https://stackoverflow.com/questions/13335881/redirecting-to-previous-page-after-authentication-in-node-js-using-passport-js

반응형