パスポートを理解する


337

Passportのシリアライズおよびデシリアライズメソッドのワークフローを素人にどのように説明しますか。

  1. どこに呼び出されたuser.idpassport.serializeUserですか?

  2. それのpassport.deserializeUser直後に、ワークフローのどこに収まるかを呼び出します。

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

私はまだ頭を包み込もうとしています。完全に機能するアプリがあり、どのようなエラーも発生していません。

ここで何が起こっているのか正確に理解したかっただけですか?

どんな助けでもありがたいです。

回答:


451
  1. どこに呼び出されたuser.idpassport.serializeUserですか?

ユーザーID(done関数の2番目の引数として指定)はセッションに保存され、後でdeserializeUser関数を介してオブジェクト全体を取得するために使用されます。

serializeUserユーザーオブジェクトのどのデータをセッションに保存するかを決定します。serializeUserメソッドの結果は、セッションにとしてアタッチされreq.session.passport.user = {}ます。たとえば、ここでは(ユーザーIDをキーとして提供するため)req.session.passport.user = {id: 'xyz'}

  1. それのpassport.deserializeUser直後に、ワークフローのどこに収まるかを呼び出します。

の最初の引数はdeserializeUserdone関数に与えられたユーザーオブジェクトのキーに対応します(1を参照)。そのため、そのキーを使用してオブジェクト全体が取得されます。ここでのキーはユーザーIDです(キーはユーザーオブジェクトの任意のキー、つまり名前、電子メールなど)。にdeserializeUserそのキーのメモリにアレイ/データベースまたはデータリソースと一致します。

フェッチされたオブジェクトは、リクエストオブジェクトに次のようにアタッチされます。 req.user

視覚的な流れ

passport.serializeUser(function(user, done) {
    done(null, user.id);
});              
                  
                 
                 └─────────────────┬──→ saved to session
                                       req.session.passport.user = {id: '..'}
                                   
                                              
passport.deserializeUser(function(id, done) {
                   ┌───────────────┘
                   
                    
    User.findById(id, function(err, user) {
        done(err, user);
    });            └──────────────→ user object attaches to the request as req.user   
});

2
だから、さuser.idとして保存req.session.passport.userまたはされuser、それ自体として記憶req.session.passport.user
Anubhav

@AB私は、最初のパラメーターとしてdeserializeメソッドに渡されたIDからユーザーを見つけるコードを書きました。しかし、すべてのリクエストでdbからユーザーを取得しています。これにより、dbのパフォーマンスが低下します。セッションに存在するかどうかを確認するために、関数をデシリアライズする他に何を書く必要がありますか?
uzay95 2016

2
@AB uzay95への提案を理解できません。したがって、私のセッションでは、user._idしかありません。しかし、すべてのリクエストで、そのIDを使用してデータベースから逆シリアル化する必要があります。すべてのリクエストでこのような呼び出しを行わないようにするにはどうすればよいですか?
Zanko

10
@Zankoユーザーオブジェクト全体をセッションデータに入れることもできますが、他の副作用が発生する可能性があるため、通常はお勧めできません。たとえば、ユーザーがユーザー名を更新する場合は、セッションデータも更新する必要があります。更新しない場合は、「壊れた名前変更機能」が原因でチケットを取得します。これは比較的無害な例です。同じことが許可ビットまたは同等の機密データ(おっと...)でも発生する可能性があります。データが重複している場合、基本的に常に同じ問題が発生します。TL; DR-それをしないでください。
Max Truxa 2016

1
私が誤解していない場合req.session.passport.user = {id: '..'}、図の一部はわずかにずれているので、req.session.passport.user = 785352代わりにである必要が785352ありuser.idます。それを証明するためにコンソールのロギングに問題がありますが、それは理にかなっているようです。を呼び出すときdone(null, user.id);、2番目の引数user.id(この場合は)を取り、req.session.passport.userに割り当てる代わりにに割り当てることは意味がありreq.session.passport.user.idます。代わりに渡した場合はどうなりますuserか?req.sesssion.passport.user.id = user意味がありません。
Adam

21

Koaとkoa-passportを使用している場合:

serializeUserメソッドで設定されたユーザーのキー(多くの場合、そのユーザーの一意のID)は次の場所に格納されます。

this.session.passport.user

done(null, user)deserializeUserに設定すると、「user」はデータベースのユーザーオブジェクトです。

this.req.user または this.passport.user

何らかの理由this.userで、deserializeUserメソッドでdone(null、user)を呼び出しても、Koaコンテキストは設定されません。

したがって、app.use(passport.session())を呼び出した後で独自のミドルウェアを記述して、this.userに次のように配置できます。

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

serializeUserとdeserializeUserの動作が不明な場合は、Twitterで教えてください。@yvanscher


ここでネクロポスティングを行って申し訳ありませんが、逆シリアル化の説明を読んだ後、私は今心配しています。:私はSOにここにこれについての質問を掲載しました stackoverflow.com/questions/54154047/...
ピーター・ケルナー

非常に役に立ちましたが、他のルートからユーザーを読み取る際にいくつかの問題がまだあります。誰かが私を助けてくれますか?stackoverflow.com/questions/60709882/...
ハリー・リンカーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.