Следуя этому примеру в репозитории Nextjs, я хочу реализовать защиту CSRF (возможно, с пакетом csurf ), потому что я использую cookie-файл идентификатора сеанса с express-session.
Я попытался установить csurf на моем пользовательском сервере и сохранить сгенерированный токен в res.locals.csrfToken, который можно получить при загрузке первой страницы статическим методом "getInitialProps", который находится в /lib/withApollo.js в пример, который я связал. Как только я пытаюсь изменить страницу (со ссылками) или сделать запрос на публикацию с помощью apollo (например, логин), сервер меняет токен csrf, поэтому тот, который использовался Apollo, больше не является полезным, и поэтому я получаю ошибка "csrf is invalid".
Пользовательский сервер с конфигурацией csurf
const csrf = require('csurf');
const csrfProtection = csrf();
////express-session configuration code////
app.use(csrfProtection);
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
})
/ Библиотека / initApollo.js
function create(initialState, { getToken, cookies, csrfToken }) {
const httpLink = createHttpLink({
uri: "http://localhost:3000/graphql",
credentials: "include"
});
const authLink = setContext((_, { headers }) => {
const token = getToken();
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
Cookie: cookies ? cookies : "",
"x-xsrf-token": csrfToken ? csrfToken : ""
}
};
});
/ Библиотека / withApollo.js
static async getInitialProps(ctx) {
const {
Component,
router,
ctx: { req, res }
} = ctx;
const apollo = initApollo(
{},
{
getToken: () => parseCookies(req).token,
cookies: req ? req.headers.cookie : "",
csrfToken: res ? res.locals.csrfToken : document.cookie
}
);
С помощью этой конфигурации каждый маршрут защищен от csrf, но токен, созданный на сервере, часто меняется, и Apollo не может получить обновленный токен, как только ему это нужно, поэтому первая загрузка прошла успешно, но последующее изменение страницы (ссылки) или любой пост-запрос завершается неудачно, потому что токен изменился.