Next.js集成next-csrf防护API路由时触发500服务器错误:Signed cookie string must be provided
Let's break down why you're hitting this 500 error and how to fix it quickly.
The Root Cause
The next-csrf library relies on two key pieces to validate requests:
- A signed CSRF token stored in a cookie (by default named
__Host-xsrf-token) - The same token sent in the
XSRF-TOKENrequest header
Your current setup passes the token in the request header, but you never initialize and set the required cookie on the server side. That's why the library throws the "Signed cookie string must be provided" error—it can't find the cookie it needs to verify the header value.
The Fix: Initialize the CSRF Cookie in getServerSideProps
You need to call csrfToken() from your next-csrf setup in a server-side context (like getServerSideProps) to generate the token and automatically set the cookie on the response. Then pass that token to your page component to use in the request header.
Here's how to update your page code:
import { useState, useEffect } from 'react'; import axios from 'axios'; import { withRouter } from 'next/router'; import { Page, PostBlock } from '@/components'; import { csrfToken } from '@/lib/csrf'; // Import csrfToken from your lib const Main = ({ router, csrfToken }) => { const [postsData, setPostsData] = useState({ posts: [], page: 0, pages: 0 }); function fetchData() { axios .get('/api/articles', { headers: { 'XSRF-TOKEN': csrfToken }, params: { page: router.query?.page, lang: router.locale, tag: router.query.tag, }, }) .then(response => { setPostsData(response.data); }) .catch(error => console.log(error)); } useEffect(() => { fetchData(); }, [router.query.page, router.locale, router.query.tag]); // Add dependencies to refetch on query changes return ( <Page title='Home' className='home-template'> <div id='grid' className='post-grid'> {postsData.posts?.map(post => ( <PostBlock featured={post.featured} key={post.slug} post={post} /> // Note: You'll want to pass post data to PostBlock to render content! ))} </div> </Page> ); }; // Add this server-side function to initialize the CSRF cookie export async function getServerSideProps({ req, res }) { const token = csrfToken(req, res); return { props: { csrfToken: token }, }; } export default withRouter(Main);
Why Postman Works
Postman automatically persists cookies from previous requests. Chances are you made a request to a route that generated the __Host-xsrf-token cookie (like your page itself, if you had previously set up the cookie) and Postman kept it. When you sent the API request, it included that cookie along with the header, so validation passed. Your browser didn't have that cookie on the first load, hence the error.
Quick Additional Checks
- Verify that
process.env.CSRF_SECRETis set and not empty in your environment variables. An invalid or missing secret will cause signature validation failures. - If you only need CSRF protection for data-modifying requests (POST/PUT/DELETE), you can configure
next-csrfto skip GET requests by addingignoredMethods: ['GET']to your options in/lib/csrf.js:
This is optional but can simplify things if your GET requests don't alter data.const options = { secret: `${process.env.CSRF_SECRET}`, ignoredMethods: ['GET'] };
内容的提问来源于stack exchange,提问作者ste

