NextJS:不刷新就无法获取客户端cookie
NextJS: Can't get client side cookies without refreshing
当用户登录时,我将 cookie 设置为 js-cookie
用于客户端访问。
我认为 cookie 必须是客户端可访问的,因为我使用 Redux Toolkit for async thunk requests。
export async function apiLogin({ email, password }) {
const data = JSON.stringify({
email,
password,
});
const config = {
method: 'post',
url: `${process.env.API_URL}/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data,
};
const response = await axios(config);
if (response.status === 200 && response.data) {
const encodedUser = Buffer.from(JSON.stringify(response.data.user)).toString('base64');
Cookies.set('token', response.data.token, { expires: 1 });
Cookies.set('user', encodedUser, { expires: 1 });
return { user: response.data.user, token: response.data.token };
}
if (response.status === 401) {
return { error: 'User/pw incorrect' };
}
return { error: 'Error' };
}
登录时正确设置了这些 cookie - 我可以在 Dev Tools 的应用程序选项卡中看到它们。
但是,我以后的请求无法访问这些 cookie:
import Cookies from 'js-cookie';
const cookieToken = Cookies.get('token') // this is throws null unless I refresh
export const axiosInstance = (token = cookieToken) => axios.create({
baseURL: process.env.API_URL,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`,
},
});
请求示例:
browse(params = {}, hook = null) {
return axiosInstance()
.get(endpoint, { params })
.then((response) => {
const { data } = response;
if (hook) {
data.items = data.items.map((item) => hook(item));
}
return data;
})
.catch((error) => console.error('error', error));
},
cookie getter 方法工作正常,但前提是我刷新页面。所以我认为这不是问题。
编辑:不是 axios
问题,我对本机 fetch
API 做了同样的事情,但仍然无法获取 cookie。我还尝试将 token
保存在 localStorage
中,结果相同。
编辑2:
我忘了说我有一个 _middleware.js
文件,它仅在令牌存在时才对路由添加保护,而且效果很好,所以我猜服务器端令牌是可访问的:
export function middleware(req) {
const userSession = req.headers.get('cookie');
const url = req.nextUrl.clone();
if (userSession?.includes('token')) {
console.log(userSession); // token is there!
if (req.nextUrl.pathname === '/login') {
url.pathname = '/';
return NextResponse.redirect(url);
}
return NextResponse.next();
}
url.pathname = '/login';
return NextResponse.rewrite(url);
}
好吧,花了这么多时间来解决这个问题,感觉有点尴尬,但显然设置一个名称为 token
的 cookie 令牌是行不通的,在尝试了其他几种方法后,它看起来很简单将其命名为 cookieToken
就可以了。喵.
当用户登录时,我将 cookie 设置为 js-cookie
用于客户端访问。
我认为 cookie 必须是客户端可访问的,因为我使用 Redux Toolkit for async thunk requests。
export async function apiLogin({ email, password }) {
const data = JSON.stringify({
email,
password,
});
const config = {
method: 'post',
url: `${process.env.API_URL}/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data,
};
const response = await axios(config);
if (response.status === 200 && response.data) {
const encodedUser = Buffer.from(JSON.stringify(response.data.user)).toString('base64');
Cookies.set('token', response.data.token, { expires: 1 });
Cookies.set('user', encodedUser, { expires: 1 });
return { user: response.data.user, token: response.data.token };
}
if (response.status === 401) {
return { error: 'User/pw incorrect' };
}
return { error: 'Error' };
}
登录时正确设置了这些 cookie - 我可以在 Dev Tools 的应用程序选项卡中看到它们。
但是,我以后的请求无法访问这些 cookie:
import Cookies from 'js-cookie';
const cookieToken = Cookies.get('token') // this is throws null unless I refresh
export const axiosInstance = (token = cookieToken) => axios.create({
baseURL: process.env.API_URL,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`,
},
});
请求示例:
browse(params = {}, hook = null) {
return axiosInstance()
.get(endpoint, { params })
.then((response) => {
const { data } = response;
if (hook) {
data.items = data.items.map((item) => hook(item));
}
return data;
})
.catch((error) => console.error('error', error));
},
cookie getter 方法工作正常,但前提是我刷新页面。所以我认为这不是问题。
编辑:不是 axios
问题,我对本机 fetch
API 做了同样的事情,但仍然无法获取 cookie。我还尝试将 token
保存在 localStorage
中,结果相同。
编辑2:
我忘了说我有一个 _middleware.js
文件,它仅在令牌存在时才对路由添加保护,而且效果很好,所以我猜服务器端令牌是可访问的:
export function middleware(req) {
const userSession = req.headers.get('cookie');
const url = req.nextUrl.clone();
if (userSession?.includes('token')) {
console.log(userSession); // token is there!
if (req.nextUrl.pathname === '/login') {
url.pathname = '/';
return NextResponse.redirect(url);
}
return NextResponse.next();
}
url.pathname = '/login';
return NextResponse.rewrite(url);
}
好吧,花了这么多时间来解决这个问题,感觉有点尴尬,但显然设置一个名称为 token
的 cookie 令牌是行不通的,在尝试了其他几种方法后,它看起来很简单将其命名为 cookieToken
就可以了。喵.