web-dev-qa-db-ja.com

Node JS + Passport + RedisStoreのシリアライズとデシリアライズを実装しますか?

シリアライズとデシリアライズを実装しますか?

RedisStoreは、Expressを使用したセッションストアとして設定されています。これは、シリアライズとデシリアライズを実装しないことを意味しますか?自動的に発生しますか?

これらのメソッドを実装しないと、次のExpressエラー-500エラー:ユーザーをセッションにシリアル化できませんでした。私がそれらを実装するとき、私はDeserializeに何を入れるかわかりません。

以下のコードは機能しているようですが、セッションが持続していません。サイトにアクセスするたびにログインする必要があります。

NodeJS + Passport + RedisStoreの良い例はありますか?

var sessionStore = new RedisStore({
                                        Host: rtg.hostname,
                                        port: rtg.port,
                                        db: redisAuth[0],
                                        pass: redisAuth[1]
                                      });

passport.use(new ForceDotComStrategy({
    clientID: clientId,
    clientSecret: clientSecret,
    callbackURL: myurl
},
function(token, tokenSecret, profile, done) {
    console.log(profile);
    return done(null, profile);
  }
));

appSecure.configure('production', function(){
appSecure.use(allowCrossDomain);
appSecure.use(express.cookieParser(expressSecret));
appSecure.use(express.bodyParser());
appSecure.use(express.methodOverride());
appSecure.set('port', port); 
appSecure.use(express.session({ secret: expressSecret, store: sessionStore, key:'expressSid', cookie: { maxAge : 604800, domain:'.domain.com'}})); 
appSecure.use(passport.initialize());
appSecure.use(passport.session());
appSecure.use(appSecure.router);
appSecure.use(express.static(__dirname + '/public'));
appSecure.use(express.errorHandler());
});

passport.serializeUser(function( user, done ) {
    done( null, user.id);
});

passport.deserializeUser(function( user, done ) {
    done( null, user );
});
18
wisemanIV

sessionsを使用している場合は、パスポートにシリアライズおよびデシリアライズ機能を提供する必要があります。セッションストアとしてのRedisの実装は、パスポートの実装方法とは関係なく、セッションデータが格納されている場所のみを扱います。

パスポートを使用したセッションの実装

すでに述べたように、セッションを機能させるには、シリアライズおよびデシリアライズ機能をパスポートに提供する必要があります。

serialize関数の目的は、後続の要求でユーザーアカウントを復元するために十分な識別情報を返すことです。具体的には、done()メソッドの2番目のパラメーターは、セッションデータにシリアル化された情報です。

提供するdeserialize関数は、セッションにシリアル化された識別情報に基づいてユーザープロファイルを返すことを目的としています

以下は、セッションについて説明しているセクションの パスポートガイド の例です。

_passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});
_

上記の例では、passport.serializeUser()には、ユーザープロファイル(user)とコールバック関数(done)の2つのパラメーターを取る関数が提供されています。コールバック関数は、2番目のパラメーターとして識別情報(_user.id_を受け取りますが、mongoDBを使用している場合は、データベースからアカウントを回復するために_user._id_)が必要になる場合があります。これは、認証されたすべてのリクエストで呼び出され、識別情報をセッションデータに保存します(Cookieでも、Redisストアでも)。

passport.deserializeUser()には、識別情報(id)とコールバック関数(done)の2つのパラメーターも受け取る関数が用意されています。識別情報は、前の要求(_user.id_)でセッションデータにシリアル化されたものです。ここでのコールバック関数は、2番目のパラメーターとしてのユーザープロファイル、または最初のパラメーターとしてのプロファイルの取得で発生したエラーを必要とします。 User.findById()関数は、データベース内のユーザープロファイルの検索関数です。この例では、Userオブジェクトは findById() 関数を持つマングースモデルのインスタンスです。

passport.deserializeUser()に提供される関数は、パス処理ミドルウェアpassport.session()によってルート処理の前に呼び出され、ユーザープロファイル(user)を_req.user_に保存します。

セッションストアとしてのRedisの実装

Redisを使用する目的は、セッションデータをサーバー側に格納することであり、クライアント側に格納されるデータはセッションIDのみです。繰り返しますが、これはパスポートの実装方法に依存しません。パスポートは、アプリにセッションサポートを追加している限り、セッションデータの保存場所を気にしません。 stackoverflowに関するこの前の質問 Redisの実装方法に対処します

46
Weston

少し遅れましたが、私はこの視覚的なことを理解させました

  1. いつ/どのようにして戦略/ローカル/ Facebook /などが呼び出され、どのようにreq.loginまたはpassport.serializeUser()に到達し、done()でどうなりますか?

passport.authenticate()は、引数として指定したそれぞれの戦略を呼び出します。ここで、_req.body.password_および_req.body.username_を、データベースまたはメモリに保存されたパスワードとユーザー名に一致させます。ユーザーが2番目の引数としてdone()に渡した場合、それ以外の場合は_return false_

完了したコールバックはpassport.authenticate()に戻ります。 doneが以前にユーザー(つまりdone(null,user);)で呼び出された場合、req,logIn()は自動的に、またはユーザーの背後で呼び出されます

req.logIn()呼び出しpassport.serializeUser()

  1. Whats passport.serializeUserと、この関数が呼び出された後のuser.some_keyの場所

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

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

  1. Passport.deserializeUserとは何ですか?それはワークフローのどこに適合しますか?

デシリアライズ関数では、デシリアライズ関数の最初の引数に、シリアライズ呼び出しで関数を実行するために渡されたユーザーオブジェクトの同じキーを指定します。そのため、そのキーを使用してオブジェクト全体が取得されます。ここでのキーはidです(keyはユーザーオブジェクトの任意のキー、つまり名前、電子メールなどです)deSerialize関数では、そのキーはメモリアレイ/データベースまたは任意のデータリソースで照合されます

フェッチされたオブジェクトは、_req.user_としてリクエストオブジェクトにアタッチされます

idキーは、ユーザーオブジェクトの任意のキー、つまり_name,email_などにすることができます

ビジュアルフロー

_passport.authenticate()-----------
                                 |  
                                 |  invokes 
                                \./
       passport.use(new LocalStrategy(
            function(username, password, done) {

           // match req.body.username and req.body.password from any 
              //data base or in memory array
               if(user_is_found_and_pass_match)
                  done(null,user);--
               else                   | *1-user passed
                                      |
                  done(null,false);---| *2-user not passed
       });                            | 
                                      |return back to
passport.authenticate() <------------ |
                      |
                      |----- if user is passed in done() (*1) ,   
                            |
    req.login()   <--------- 
              |
 //authenticate() middleware  may  invoke req.login() automatically.
              |
              | calls
             \./  
 passport.serializeUser(function(user, done) {
        done(null, user.id); 
                     |
//use 'id'to serialize, you can use other or user object itself
    });              |-->saved to session req.session.passport.user = {id:'..'}
                     |
                     |__________________
                                       |          
    passport.deserializeUser(function(id, done) {
                      ________________|
                      | 
        User.findById(id, function(err, user) {
            done(err, user);
                       |______________>user object ataches to the request as req.user

     });
      });
_

ここでidキーは、ユーザーオブジェクトの任意のキー、つまり_name,email_などにすることができます

25
A.B

セッションストアとしてexpress-sessionを使用したconnect-redisの次の構成があるとします(Express 4を使用)。

redis = require('redis').createClient(6379, '127.0.0.1');
session = require('express-session');
RedisStore = require('connect-redis')(session);

app.use(session({
  store: new RedisStore({
    client: redis
  }),
  secret: 's3cret',
  resave: true,
  saveUninitialized: true
}));

ユーザーIDだけでなく、ユーザーオブジェクト全体をシリアル化するようにパスポートに指示するだけです。

passport.serializeUser(function(user, done){
  done(null, user);
});

passport.deserializeUser(function(user, done){
  done(null, user);
});

ユーザーオブジェクト全体がRedisのセッションと共に保存され、すべてのリクエストに対してreq.userとしてリクエストに配置されます。

11
Andrew Homeyer