5

新しいユーザー アカウントが作成されたら、次のような Mongoose モデル インスタンスである newUser を作成します。

_events: Object
errors: undefined
isNew: false
save: function () {
arguments: null
caller: null
_doc: Object
  name: 'Joe Smith'
...

オブジェクトの実際のデータは_docプロパティにありますが、ゲッターとセッターが存在するため、次を実行できます。

user.name = 'Jane Doe' 

そしてそれはうまくいくでしょう。走る:

request.session.user = newUser;

ユーザーをセッションに保存します。ここまでは順調ですね。

ただし、その後のリクエストでは、request.session.user は _doc のものだけのようです。例えば:

name: 'Joe Smith'

これはいいことですが、たとえばrequest.session.user.save()を実行して変更を保存できないことを意味します。

データに関連付けられたユーザーを検索するためのミドルウェアを簡単に作成できます。しかし、Express と Mongoose がここで何をしているのか、もっと知りたいです。

request.session.user を Mongoose モデルにするにはどうすればよいですか?

更新:私の現在のミドルウェアハック:

// Use as a middleware on routes which need users
// TODO: only needed due to request.session.user being saved weirdly
var rehydrateUser = function(request, response, next) {
  if ( request.session.user ) {
    var hydrated = request.session.user.save
    if ( ! hydrated ) {
      console.log('Rehydrating user...');
      models.User.findOne({ somefield: request.session.user.somefield }, function (err, user) {
        if ( err ) {
          request.session.error = 'User not found in DB!';
          request.redirect('/');
        } else {
          request.session.user = user;          
          console.log('Rehydrated user! All repos already being monitored.');
          next();
        }
      })
    } else {
      next();
    }
  } else {
    console.log('No user in session')
    next();
  }
}
4

3 に答える 3

11

Express セッションは別のストレージとして保存され、そこに保存できるものには制限があります。プロトタイプ データ (メソッド) を格納することはできません。key<>valueストレージのように見てください。

この理由は、次のような場所に (ほとんど) セッションを格納できるためです。プロセス メモリ。データベース (mongodb); レディス; 等

このため、セッションオブジェクトに何かを入れてリクエストが完了すると、エクスプレスはセッションデータを取得して解析し、純粋なオブジェクトと同じようにセッションストアに貼り付けます。デフォルトではプロセスメモリですが、前述のように、他のストレージでもかまいません。

そのため、次の http リクエストが発生すると、セッション ミドルウェアは、リクエスト ヘッダー内の Cookie (使用されている場合) データを使用してセッションを復元しようとし、セッション ストレージにデータを返すように要求します。すでにフォーマットされているため、.prototype は含まれず、データ ( objectarraystringnumberおよびその他の単純なもの) のみが含まれます。

そのため、そのデータからモデルを再度作成する必要があります。
Expressのミドルウェアでできます。したがって、app.configure定義した直後にsession これを行うことができます:

app.use(function(req, res, next) {
  if (req.session && req.session.user) {
    req.session.user = new UserModel(req.session.user);
  }
  return next();
});

これにより、ユーザーだけでなくセッションも定義されているかどうかがチェックされます。そして、そのデータからマングース モデルを再作成します。

ここのコメントで述べたように、データの所有権に対する責任の分割により矛盾が生じるため、ユーザー データをセッションに保存しないでください。したがってID、ユーザーだけを保存し、ミドルウェアを使用してデータベースからロードします。

app.use(function(req, res, next) {
  if (req.session && req.session.userID) {
    UserModel.findById(req.session.userID, function(err, user) {
      if (!err && user) {
        req.user = user;
        next();
      } else {
        next(new Error('Could not restore User from Session.'));
      }
    });
  } else {
    next();
  }
});

ユーザーがログインしているかどうかを確認するミドルウェアを作成できたら、次のようにします。

function userRequired(req, res, next) {
  if (req.user) {
    next();
  } else {
    next(new Error('Not Logged In');
  }
}

そして、そのように使用します:

app.get('/items', userRequired, function(req, res, next) {
  // will only come here if user is logged in (req.user !== undefined)
});
于 2013-09-06T16:47:48.430 に答える
0

ユーザー オブジェクト全体を保持するためにセッション ストアに依存することには複雑な問題がありますが、メソッドを使用してプレーンな JS オブジェクトから mongoose オブジェクトを初期化できることに注意してくださいinit()(この記事の執筆時点では v4.4.14)。

req.user = new UserModel().init(req.session.user);
req.user.name = 'James';
req.user.save( ... );

これは好きではありません( 更新するのではなく、同じもので新しいドキュメントを保存しようとします):_id

req.session.user = new UserModel(req.session.user);
req.user.name = 'James';
req.user.save( ... );
于 2016-05-02T20:30:45.137 に答える