在Nextjs存储库中的此示例之后,我想实现CSRF保护(也许使用csurf程序包),因为我正在使用带有Express-Session的会话ID Cookie。
我尝试在自定义服务器中设置csurf并将生成的令牌保存在res.locals.csrfToken中,该页面在第一次加载时就可以通过示例中/lib/withApollo.js中的静态方法“ getInitialProps”获取链接。一旦我尝试更改页面(带有链接)或尝试使用apollo(例如登录)发出发布请求,服务器便更改了csrf令牌,因此Apollo使用的令牌不再有用,因此我得到了“ csrf无效”错误。
具有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();
})
/lib/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 : ""
}
};
});
/lib/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无法在需要时立即检索更新的令牌,因此第一次加载成功,但是随后的页面更改(链接)或任何发布请求失败,因为令牌已更改。
更新资料
经过如此多的浏览,我终于能够发送csrf cookie。我认为问题在于单词
return
。当您使用return时,它会排除cookie。这是我通过编辑所做的/lib/initApollo.js
。e!但是,SSR没有cookie。我认为我们应该有两个来自客户端的端点,另一个应该是SSR。SSR网址可以被csrf豁免。