ログインページはありませんが、すべてのページに表示されるログインフォームがあります。認証が成功したかどうかに関係なく、ユーザーをリダイレクト先の同じページにリダイレクトしたい(適切なフラッシュメッセージを使用)
次のコードを見てください。
app.post('/login', validateLogin, passport.authenticate('local-login'), function(req, res) {
var redirectUrl = '/';
if(req.body.to.length > 0){
redirectUrl = req.body.to;
}
console.log("THIS IS ONLY CALLED IF passport.authenticate() IS SUCCESSFUL");
res.redirect(redirectUrl);
});
上記の最後のミドルウェアが呼び出されるのは、認証に合格した場合のみです。失敗した場合、パスポートがgetリクエストの形式で/ loginにリダイレクトしているようです。私のアプリでは、このページは存在しません。
追加のオプションオブジェクトをパスポート認証関数のパラメーターとして渡すと、次のように機能します。
app.post('/login', validateLogin, passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page. THIS IS JUST FOR TESTING TO SEE IF THE REDIRECT ON FAIL WORKS.
failureFlash : true, // allow flash messages
}
));
しかし、これを行うと、ユーザーをリダイレクトする場所を選択できなくなります。認証が失敗した場合、パスポートがユーザーのリダイレクト先を制御するようです。どうすれば修正できますか?それともバグですか?認証が失敗した場合、パスポート認証はチェーンの最後のミドルウェアでなければなりませんか?
これは私のローカル戦略関数呼び出しです:
//LOCAL LOGIN
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
console.log("IN PASSPORT");
if(email.length == 0 || password.length == 0){
console.log("FIELDS ARE EMPTY");
return done(null, false, req.flash('loginMessage', 'Fill in all values.'));
}
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ 'local.email' : email }, function(err, user) {
// if there are any errors, return the error before anything else
if (err){
return done(err);
console.log("db err");
}
// if no user is found, return the message
if (!user){
console.log("not user");
return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // req.flash is the way to set flashdata using connect-flash
}
// if the user is found but the password is wrong
if (!user.validPassword(password)){
console.log("invalid pw");
return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // create the loginMessage and save it to session as flashdata
}
// all is well, return successful user
console.log("All OK");
return done(null, user);
});
}));
そこの最後の段落で説明されているように、カスタム認証コールバックを使用できます http://passportjs.org/guide/authenticate/ 。
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
// Redirect if it fails
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
// Redirect if it succeeds
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
成功したFacebook Authに続くリダイレクト呼び出しと同じ問題に遭遇しました
..尊敬されていませんでした。
「ローカル」のpassportJS戦略に基づいており、そのことを @ ploutchの回答はこちら ..から通知しています。これを機能させるための鍵は、次の呼び出しにあるようです。
req.logIn(user, function(err) {
...
}
Facebookの場合、このルート設定は私にとってうまくいきました:
app.get(
'/auth/facebook/callback',
passport.authenticate
(
'facebook',
{ failureRedirect: '/fbFailed' }
),
function(req, res)
{
var user = myGetUserFunc(); // Get user object from DB or etc
req.logIn(user, function(err) {
if (err) {
req.flash('error', 'SOMETHING BAD HAPPEND');
return res.redirect('/login');
}
req.session.user = user;
// Redirect if it succeeds
req.flash('success', 'Fb Auth successful');
return res.redirect('/user/home');
});
}
);
これは、提案されたすべてのオプションを試してもうまくいかなかった私のような一部の人々にとって、まだ問題である可能性があることを知っています。
私の場合、結局のところ、req.bodyオブジェクトが常に空であるため、エラーが発生していました。ボディ解析ミドルウェアを正しくセットアップしていたので、なぜこれが起こっているのか理解できませんでした。
さらに調査した結果、フォーム(multipart/form-data)に使用していたenctypeがbody-parserでサポートされていないことがわかりました。別のミドルウェアに切り替えた後、 read me を参照してください。モルター、すべてがスムーズに動作しました。
以下を含む完全な回答:
redirectTo
ミドルウェアにloginRequired
値を作成するだけです。
var loginRequired = function(req, res, next) {
if ( req.isAuthenticated() ) {
next();
return
}
// Redirect here if logged in successfully
req.session.redirectTo = req.path;
res.redirect('/login')
}
そして、あなたのログインPOSTで:
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if ( err ) {
next(err);
return
}
// User does not exist
if ( ! user ) {
req.flash('error', 'Invalid email or password');
res.redirect('/login');
return
}
req.logIn(user, function(err) {
// Invalid password
if ( err ) {
req.flash('error', 'Invalid email or password');
next(err);
return
}
res.redirect(req.session.redirectTo || '/orders');
return
});
})(req, res, next);
});