2017-06-20 5 views
0

私はパスポートjsを使ってエクスプレスjs apiをビルドしています.jsonとしてフォーマットされたカスタムエラーメッセージを返すためにはcustom callbacksを使用しています。Passport JS 3回コールされたカスタムコールバック

私が未知の電子メールを提供したとき、私が書いたカスタムコールバックは3回呼び出され、Unhandled rejection Error: Can't set headers after they are sent.という結果になりました。どちらが理にかなっている。

何か助けていただければ幸いです。

戦略:カスタムコールバックを使用して認証用の

const localLoginStrategy = new LocalStrategy({ 
    usernameField: "emailAddress" 
}, (emailAddress, password, done) => { 
    // Called once 
    User.findOne({ 
     where: { emailAddress } 
    }).then((existingUser) => { 
     // Called once 
     if (!existingUser) { return done(null, false, { message: "Invalid email/password combination", status: 401 }); } 

     return existingUser.comparePassword(password); 
    }).then((userData) => { 
     return done(null, userData); 
    }).catch((err) => { 
     return done(null, false, { message: "Invalid email/password combination", status: 401 }); 
    }); 
}); 

passport.use(localLoginStrategy); 

エクスプレスミドルウェア:

const requireUsernamePassword = (req, res, next) => { 
    if(!req.body.emailAddress || !req.body.password) { 
     return res.status(400).json({ message: "No emailAddress and/or password provided" }); 
    } 
    // Called once 
    passport.authenticate("local", { session: false }, (err, user, info) => { 
     // Called three times! 
     console.log("authenticate callback") 
     if (!user || err) { 
      return res 
       .status(info.status || 400) 
       .json({ message: info.message || "Authentication error" }); 
     } 
     req.user = user; 
     return next(); 
    })(req, res, next); 
}; 
+0

requireUsernamePasswordミドルウェアとは何を呼びますか?複数のコールがコールスタックの早い段階から来ることはできますか? '返品User.findOne(....)'を追加しようとしてもらえますか?それはそれが原因だとは思えませんが、それは傷つき、一般的には必ずしも約束を返す良い習慣です。 3回の通話ごとにerr/user/infoの値を記録しましたか? – Boris

答えて

1

あなたはdone関数を複数回呼び出している

は、ここに私の実装です。

thenメソッドでreturn done(...)を呼び出すと、次のthendoneに戻ります。

callbackの機能が時間外に呼び出された理由です。

希望します。

+0

私はいつも約束に苦しんでいます、あなたが答えた時点で私はそれを理解しましたが、これは正解です。 – Alexander

1

必須の必須項目のフィールドを確認するには、必須フィールドをチェックして適切な戻りコードを返す汎用ミドルウェアを作成します。ちょうど以下のように。

module.exports = function checkParams(params) { 
    params = params || []; 
    return function(req, res, next) { 
    var valid = true; 
    if(Array.isArray(params)) { 
     params.forEach(function(_param) { 
     valid = valid && !!req.body[_param]; 
     }); 
    } 
    if (valid) { next() } else {return res.status(400).end();} //this is for missing required parameters 
    }; 
}; 

たとえば、2つのAPIがあるとします。ログインとCreateUser。これらのパラメータ(ユーザ名と電話/でCreateUser + EMAILADDRESS中および/ログインでパスワード)のいずれかが、それは400件のステータスを返すと、その時点から実行を停止します欠落している場合は、APIのルートは、あなたは、

app.post('/Login', checkParams(['emailAddress', 'password']), passport.authenticate('local', { failureRedirect: '/login' }), actualLoginMethod); 


app.post('/CreateUser', checkParams(['userName', 'Phone']), passport.authenticate('local', { failureRedirect: '/login' }), actualCreateUserMethod); 

以下のようにも見えます必要があります必要に応じてcheckParamsのロジックを変更してください。

必要なパラメータが利用可能な場合、JWTローカル戦略をチェックします。リクエストが両方のチェックポイントに通されると、実際のメソッドが呼び出されます。

これはあなたに役立つと思います。

+0

私はあなたのアイデアが気に入っていますが、私が持っていた問題はそれほどありませんでした。私はチェックparams関数を実装します。 – Alexander

関連する問題