Как провести две экспресс-сессии?

У меня есть приложение, использующее Passport, с конечной точкой GraphQL и конечной точкой /logout. По какой-то причине, когда я вызывал request.isAuthenticated() из конечной точки GraphQL, я возвращал true, но когда я делал точно такой же вызов из конечной точки /logout, я возвращал false.

Итак, я немного запротоколировал (из request.session.id) и оказалось, что каким-то образом у меня получилось две сессии. Что еще более странно, сеанс, используемый моей конечной точкой GraphQL, является постоянным: если я перезапущу сервер, он сохранит тот же идентификатор, в то время как идентификатор в /logout продолжает меняться.

Я думаю, что происходит из-за того, что постоянный сеанс основан на файлах cookie/базе данных и поэтому восстанавливается, когда мой клиент делает свой первый запрос, в то время как сеанс /logout не основан на файлах cookie и сбрасывается с помощью сервер. Чего я не понимаю, так это почему у меня две сессии!

Вот соответствующий код:

// Session setup
const store = new KnexSessionStore({ knex, tablename: 'sessions' });
app.use(
  session({
    cookie: { maxAge: 1000 * 60 * 60 * 24 * 5},
    secret: `a secret`,
    store
  })
);

// Passport setup
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));

app.use(passport.initialize());
app.use(passport.session());

// GraphQL Setup
// NOTE: request.session.id from inside a function in schema = persistent session
const graphQLHandler = graphqlHTTP(request =>({ graphiql: true, schema }));
app.use('/graphql', graphQLHandler);

// Logout Setup
app.get('/logout', (request, response) => {
  // NOTE: request.session.id = non-persistent session
  response.send(`user has been logged out`); // someday do request.logout()
});

Как видите, функция экспресс-настройки сеанса (session) вызывается только один раз. Я вызываю app.use(passport.session()) (что похоже на создание второго сеанса), но я понимаю, что эта строка просто говорит Passport использовать сеанс... он не создает отдельный параллельный сеанс.

Может ли кто-нибудь объяснить, что происходит и как я могу заставить свое приложение делиться одним сеансом? Или, в качестве альтернативы, если кто-нибудь может объяснить, где я мог бы добавить код для выдачи ошибки при создании сеанса (чтобы я мог выяснить, какая часть моего кода создает второй сеанс), это тоже было бы полезно.


person machineghost    schedule 13.02.2018    source источник


Ответы (1)


Я нашел ответ! По-видимому, эта проблема возникла не только у меня: https://github.com/jaredhanson/passport/issues/244. Там можно прочитать все подробности, но...

TLDR: мой клиент fetch-передавал /logout с сервера. Однако по умолчанию fetch не устанавливает параметр { credentials: 'same-origin' }, и, по-видимому, вам нужно указать это, иначе Passport просто молча начнет создавать дубликаты сеансов :(

Так что оказалось, что с моим серверным кодом все в порядке, исправление просто делало следующее на стороне клиента:

fetch(`/logout`, { credentials: 'same-origin' });

Мы надеемся, что сотрудники Passport начнут выдавать ошибки, предупреждения или что-то еще в ответ на этот случай, вместо того, чтобы позволять своим бедным пользователям сбиваться с толку из-за необъяснимого, но распространенного результата (комментарий с ответом получил 15 лайков).

person machineghost    schedule 13.02.2018