node.js 使用passport.js在node.js中进行身份验证后重定向到上一页
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13335881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirecting to previous page after authentication in node.js using passport.js
提问by Alx
I'm trying to establish a login mechanism using node.js, express and passport.js. The Login itself works quite nice, also sessions are stored nicely with redis but I do have some troubles with redirecting the user to where he started from before being prompted to authenticate.
我正在尝试使用 node.js、express 和passport.js 建立登录机制。登录本身工作得很好,会话也可以很好地存储在 redis 中,但是在提示进行身份验证之前,我确实在将用户重定向到他开始的位置时遇到了一些麻烦。
e.g. User follows link http://localhost:3000/hiddenis then redirected to http://localhost:3000/loginbut then I want him to be redirected again back to http://localhost:3000/hidden.
例如,用户关注链接http://localhost:3000/hidden然后被重定向到,http://localhost:3000/login但我希望他再次被重定向回http://localhost:3000/hidden.
The purpose of this is, if the user access randomly a page he needs to be logged in first, he shall be redirected to the /login site providing his credentials and then being redirected back to the site he previously tried to access.
这样做的目的是,如果用户随机访问一个他需要先登录的页面,他将被重定向到 /login 站点,提供他的凭据,然后被重定向回他之前尝试访问的站点。
Here is my login post
这是我的登录帖子
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);
});
and here my ensureAuthenticated Method
这里是我的 ensureAuthenticated 方法
function ensureAuthenticated (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
}
which hooks into the /hiddenpage
哪个挂钩到/hidden页面
app.get('/hidden', ensureAuthenticated, function(req, res){
res.render('hidden', { title: 'hidden page' });
});
The html output for the login site is quite simple
登录站点的 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>
采纳答案by chovy
I don't know about passport, but here's how I do it:
我不知道护照,但这是我的做法:
I have a middleware I use with app.get('/account', auth.restrict, routes.account)that sets redirectToin the session...then I redirect to /login
我有一个中间件我使用app.get('/account', auth.restrict, routes.account)的是套redirectTo在会议...然后我重定向到/登录
auth.restrict = function(req, res, next){
if (!req.session.userid) {
req.session.redirectTo = '/account';
res.redirect('/login');
} else {
next();
}
};
Then in routes.login.postI do the following:
然后在routes.login.post我执行以下操作:
var redirectTo = req.session.redirectTo || '/';
delete req.session.redirectTo;
// is authenticated ?
res.redirect(redirectTo);
回答by linuxdan
In your ensureAuthenticatedmethod save the return url in the session like this:
在您的ensureAuthenticated方法中,将返回 url 保存在会话中,如下所示:
...
req.session.returnTo = req.originalUrl;
res.redirect('/login');
...
Then you can update your passport.authenticate route to something like:
然后,您可以将您的passport.authenticate 路由更新为:
app.get('/auth/google/return', passport.authenticate('google'), function(req, res) {
res.redirect(req.session.returnTo || '/');
delete req.session.returnTo;
});
回答by Jared Hanson
Take a look at connect-ensure-login, which works along side Passport to do exactly what you want!
看一看connect-ensure-login,它与 Passport 一起工作,完全符合您的要求!
回答by deksden
My way of doing things:
我的做事方式:
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next()
}
res.redirect( `/login?origin=${req.originalUrl}` )
};
GET /logincontroller:
获取/登录控制器:
if( req.query.origin )
req.session.returnTo = req.query.origin
else
req.session.returnTo = req.header('Referer')
res.render('account/login')
POST /logincontroller:
POST /登录控制器:
let returnTo = '/'
if (req.session.returnTo) {
returnTo = req.session.returnTo
delete req.session.returnTo
}
res.redirect(returnTo);
POST /logoutcontroller (not sure if there is 100% ok, comments are welcome):
POST /logout控制器(不确定是否 100% ok,欢迎评论):
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 ):
清除 returnTo 中间件(从除 auth 路由以外的任何路由上的会话中清除 returnTo - 对我来说它们是 /login 和 /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 isAuthenticatedmiddleware;
- on any pageyou can simply click on login URL, and after login returnto that page;
- 您可以使用isAuthenticated中间件保护一些路由;
- 在任何页面上,您只需单击登录 URL,登录后返回该页面;
回答by igneosaur
If you are using connect-ensure-loginthere is a super-easy, integrated way to do this with Passport using the successReturnToOrRedirectparameter. When used, passport will send you back to the originally requested URL or fallback to the URL you provide.
如果您正在使用connect-ensure-login,则有一种超级简单的集成方法可以使用successReturnToOrRedirect参数通过 Passport 执行此操作。使用时,passport 会将您发送回最初请求的 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
https://github.com/jaredhanson/connect-ensure-login#log-in-and-return-to
回答by Eray
Easiest (and properly) way to achieve this is setting failureRedirectand successRedirectoptions.
实现这一目标的最简单(且正确)的方法是settingfailureRedirect和successRedirectoptions。
回答by Alexander Danilov
@chovy and @linuxdan answers have bugwith not clearing session.returnToif user goes to another page after login redirect (thats doesn't require authentication) and logins through there. So add this code to their implementations:
@chovy 和@linuxdan 的答案有错误,session.returnTo如果用户在登录重定向(不需要身份验证)后转到另一个页面并通过那里登录,则无法清除。因此,将此代码添加到他们的实现中:
// 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.
如果您从登录页面执行一些 ajax 请求,您也可以排除它们。
Another approach is to use flashin ensureAuthenticated
另一种方法是使用flashinensureAuthenticated
req.flash('redirectTo', req.path)
res.redirect('/login')
And then in GET login
然后在GET登录
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
在 POST 登录
res.redirect(req.body.redirectTo || '/')
Notice that redirectTo will clear after first GET login with it.
请注意,redirectTo 将在第一次 GET 登录后清除。

