私は多くの日からこれをやろうとしていますが、私のテストはすべて失敗します...
私のプラットフォームのユーザーは、passportjs戦略(Paypal、facebook、google ...)を使用してそれらを接続します。
ユーザーが接続されたら、ヘッダーの右側に彼のニックネームを書きます。ヘッダーのhtmlコードはハンドルバーテンプレートから生成され、このパーシャルがexpressjsによって提供される場合、ニックネームやその他の情報を書き込むためにreq.userセッションオブジェクトをテンプレートに送信します...
ちなみに、これはうまく機能しますが、ユーザーが自分のプロファイルからニックネームを更新すると問題が発生します。サーバー側のセッションオブジェクトを更新できず、ユーザーがページをリロードすると、古いニックネームが再び表示されます。
また、ユーザーがページを読み込むたびにDBにユーザー情報を要求したくないので、この構成を保持したいと思います。
// -- Passport session setup
passport.serializeUser(function(user, done) { done(null, user); });
passport.deserializeUser(function(obj, done) { done(null, obj); });
ローカルを設定するための私のミドルウェア:
// -- Set accessible datas from the template
res.locals = _.extend(res.locals, {
user: req.user,
query: req.url,
title: app.config.title,
url: app.config.url
});
私の失敗:
// Trying to update req.user directly : not persistent
req.user.nickname = User.get('nickname');
// Trying to update passport session : exception error
req.session.passport.user = User.toJSON();
// Trying to replace full session object : not persistent
var session = req.session;
session.passport.user = User.toJSON();
req.session = session;
なにか提案を ?
今のところ、ログアウトしてからログインするだけです...それは本当に効率的ではありません:)
[〜#〜]編集[〜#〜]:
// Application router
var Router = require('./helpers/router.js');
// Create Express Server
var app = express().http().io();
// -- Init app router
var router = new Router(app);
// -- Framework Middleware
app.use(router.middleware);
#########################
/***
* APP ROUTER
**/
// Export router
module.exports = function(app) {
// Set instance
var router = this;
// Returns routes register & middleware methods
return {
// -- Register routes
register: function() {
requirejs(['routes'], function(routes) {
_.each(routes, function(name, route) {
app.get(route, function(req, res, next) {
requirejs(['views/'+name], function(view) {
if ( view ) {
var _view = new view(_.extend(req.params, {server: {req: req, res: res, next: next}}));
_view.render(name, req, res, next);
}
else {
next();
}
}, function (err) {
console.log('error' + err)
});
});
});
});
},
// -- Bind middleware
middleware: function(req, res, next) {
// Get the current path
console.log("Middleware :: "+req.url);
// Add user informations
res.locals = _.extend(res.locals, {
user: req.user,
query: req.url,
title: app.config.title,
url: app.config.url
});
// Go next
next();
}
}
}
これは私のために機能し、持続します:
req.session.passport.user.nickname = 'mynewnickname'
更新前にバスティングが必要になる可能性のあるルートでキャッシュを採用していますか?
(パスポートのシリアル化は同じです)
passport.serializeUser(function(user, done) { done(null, user); });
passport.deserializeUser(function(obj, done) { done(null, obj); });
私は同じ問題を抱えていて、最終的に解決策を見つけました:
var user = newDataObj;
req.login(user, function(error) {
if (!error) {
console.log('succcessfully updated user');
}
});
res.end(); // important to update session
Req.loginはserialize関数を呼び出し、新しいセッションをdbに保存します。 res.end()は重要です。それがないと、セッションは保存されません。
'serializeUser'の場合、ユーザー全体を返します...これにより、オブジェクト全体がシリアル化され、セッションの追跡に使用されるCookie内に配置されます。そのシリアル化は1回だけ発生します(セッションが確立されたとき)。次のリクエストが届くと、最初に保存したのとまったく同じユーザーオブジェクトが常に逆シリアル化され、更新は行われません。これが、データベースから編集されたユーザーを取得し(私が推測する)、セッション追跡Cookieを再作成するため、ログアウトと再ログインが機能する理由です。
この答えを確認するには、「serializeUser」にブレークポイントを設定し、ログインしたときにのみヒットすることに注意してください。
これは「updatesessionpassport js」の上位の結果の1つであるため、自分に合ったものを追加すると思いました(提供された回答は自分にはうまくいきませんでした)。
_req.session.passport.user.updatedfield= 'updatedvalue'
req.session.save(function(err) {console.log(err);}
_
req.session.save()
がないと、セッションデータは更新されません。これが誰かを助けることを願っています。
Quan Duongの答えは私にとって最も役に立ちましたが、もう少し現実的なシナリオがあります。
async function foo(req, res) {
// get some data from somewhere
const newNickname = req.body.nickname;
// update the user database somehow - e.g. mongodb
const users = db.getCollection('users');
await users.updateOne({
_id: req.user._id
}, {
$set: {
nickname: newNickname
}
});
// create a temporary copy of the user w/ the updated property
const updatedUser = req.user;
updatedUser.nickname = newNickname
// persist the change to the session
req.login(updatedUser, async(error) => {
if (error) {
res.json({
err: 'Sorry, there was an error updating your account.'
});
return;
}
/*
maybe you need to call another function from here that uses the updated info before
responding to the original request
*/
try {
await bar(req.user);
} catch (error) {
res.json({
err: 'Sorry, there was an error updating your account.'
});
return;
}
// done
res.send(200);
});
}