我正在创建网站的登录功能,但在使用后端的令牌设置 Cookie 时遇到问题。令牌已正确返回,并在 UserContext 中设置用户,但是令牌要存储在浏览器 Cookie 中的部分(例如在浏览器开发人员选项
Application
选项卡中查看时)未显示或未显示放。我不知道问题出在Login.jsx
还是useStorage.js
。以下是当前代码:
./src/hooks/useStorage.js
import { useCallback, useEffect, useState } from 'react';
import Cookies from 'js-cookie';
function useLocalStorage(key, defaultValue) {
return useStorage(key, defaultValue, window.localStorage);
};
function useSessionStorage(key, defaultValue) {
return useStorage(key, defaultValue, window.sessionStorage);
};
function useCookiesStorage(key, defaultValue, options) {
return useStorage(key, defaultValue, null, options);
};
function useStorage(key, defaultValue, storageObject, options) {
const [value, setValue] = useState(() => {
if (storageObject) {
const jsonValue = storageObject.getItem(key);
if (jsonValue != null) return JSON.parse(jsonValue);
} else {
const cookieValue = Cookies.get(key);
if (cookieValue != null) return JSON.parse(cookieValue);
}
if (typeof defaultValue === "function") {
return defaultValue();
} else {
return defaultValue;
}
});
useEffect(() => {
if (value === undefined) {
if (storageObject) {
return storageObject.removeItem(key);
} else {
return Cookies.remove(key, options);
}
}
const jsonValue = JSON.stringify(value);
if (storageObject) {
storageObject.setItem(key, jsonValue);
} else {
Cookies.set(key, jsonValue, options);
}
}, [key, value, storageObject, options]);
const remove = useCallback(() => {
setValue(undefined);
}, []);
return [value, setValue, remove];
};
export {
useLocalStorage,
useSessionStorage,
useCookiesStorage
};
./src/pages/Login.jsx
import '../assets/css/login.css';
import { Button, Col, Container, Form, Image, InputGroup, Row, Stack } from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useContext, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { GetUser, SignIn } from '../utils/Auth';
import Swal from 'sweetalert2';
import { useCookiesStorage } from '../hooks/useStorage';
import UserContext from '../UserContext';
function Login() {
const { setUser } = useContext(UserContext);
const navigate = useNavigate();
const [uidValue, setUidValue] = useState('');
const [upassValue, setUpassValue] = useState('');
const [,setToken] = useCookiesStorage('__Secure-auth.session-token', null, {httpOnly: true, secure: true, sameSite: 'Strict'});
async function LoginUser(e) {
e.preventDefault();
Swal.fire({
title: 'Logging in',
didOpen: () => {
Swal.showLoading();
},
text: 'Please wait',
showConfirmButton: false,
allowOutsideClick: false
});
const response = await SignIn(uidValue, upassValue); // Returns response message and token
if (!response || !response.token) {
Swal.close();
Swal.fire({
title: `${response.message}!`,
icon: 'error',
text: 'Try again',
timer: 2000,
timerProgressBar: false,
showConfirmButton: false,
allowOutsideClick: false
});
}
else {
setToken(response.token); // Set the Cookie '__Secure-auth.session-token'
const user = await GetUser(response.token); // returns user details
if (!user || !user._id) {
Swal.close();
Swal.fire({
title: `${response.message}!`,
icon: 'error',
text: 'Try again',
timer: 2000,
timerProgressBar: false,
showConfirmButton: false,
allowOutsideClick: false
});
}
else {
Swal.close();
Swal.fire({
title: 'Login successful!',
icon: 'success',
text: 'Redirecting to dashboard, please wait...',
timer: 2000,
timerProgressBar: false,
showConfirmButton: false,
allowOutsideClick: false
})
.then((result) => {
if (result.dismiss === Swal.DismissReason.timer) {
setUidValue('');
setUpassValue('');
setUser({ // Sets user context with details from fetch request
uid: user._id,
user: user.username,
role: user.role
});
navigate('/dashboard');
}
});
}
}
};
return (...rest of code);
};
export default Login;
我希望有人能帮助我解决我做错的事情,我对 React JS 还很陌生,并且通过基于项目的学习进行学习。
如果您在使用
httpOnly
设置具有 secure
和 js-cookie
标志的 cookie 时遇到问题,请注意,由于安全原因,httpOnly
cookie 无法通过 JavaScript 进行管理。
httpOnly
以进行测试:暂时删除 httpOnly
标志,以确保 cookie 已设置并在浏览器的开发人员工具中可见。secure
标志,请确保您正在通过 HTTPS 运行应用程序。以下是在 Express.js 中设置 cookie 的方法:
res.cookie('__Secure-auth.session-token', 令牌, { httpOnly:正确, secure: process.env.NODE_ENV === '生产', // 在生产中使用 true SameSite:“严格” });
为了进行测试,请根据需要调整标志以验证功能。