NodeJS 快速身份验证可以很好地使用Cookie,但浏览器无法设置它们[关闭]

ovfsdjhp  于 2023-05-22  发布在  Node.js
关注(0)|答案(1)|浏览(87)

**关闭。**这个问题是not reproducible or was caused by typos。目前不接受答复。

此问题是由打印错误或无法再重现的问题引起的。虽然类似的问题可能是on-topic在这里,这一个是解决的方式不太可能帮助未来的读者。
4天前关闭。
Improve this question
我在一个关于博客的个人项目中工作,问题是当项目的后端在用户即将登录时进行身份验证时,它会发送cookie,但浏览器不会保存它。
我用CORS和Axios选项尝试了很多配置,但似乎都不起作用。
app.js

require('dotenv').config();
const cors = require('cors');
const cookieParser = require('cookie-parser');
const express = require('express');
const authRoutes = require('./routes/auth.js');
const userRoutes = require('./routes/users.js');
const postRoutes = require('./routes/posts.js');

const app = express();

// --------------------------------------------------

app.use(
    cors({
        origin: [
            'https://example.com',
            'https://example.com/login',
            'https://example.com/logout',
            'https://example.com/write'
        ],
        credentials: true
    })
);
app.use(express.json());
app.use(cookieParser());

// --------------------------------------------------

app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/posts', postRoutes);

// --------------------------------------------------

module.exports = app;

auth.js

exports.login = (req, res) => {
    const sqlQuery = 'SELECT * FROM users WHERE username = ?';

    db.query(sqlQuery, [req.body.username], (err, data) => {
        if (err) return res.json(err);

        if (!req.body.username)
            return res.status(409).json('You need to add an username!');
        if (!req.body.password)
            return res.status(409).json('You need to add a password!');

        if (!data.length) return res.status(404).json('User not found!');

        const userData = data[0];
        const { password, ...other } = userData;

        // Check password
        const isPasswordCorrect = bcrypt.compareSync(req.body.password, password);

        if (!isPasswordCorrect)
            return res.status(400).json('Wrong username or password!');
        // -----------------------------------------------------------

        const token = jwt.sign({ id: other.id }, process.env.JWT_KEY);

        res
            .cookie('access_token', token, {
                httpOnly: false,
                sameSite: 'none',
                secure: true,
                domain: 'example.com'
            })
            .status(200)
            .json(other);
    });
};


exports.logout = (req, res) => {
    res
        .clearCookie('access_token', {
            httpOnly: false,
            sameSite: 'none',
            secure: true,
            domain: 'example.com'
        })
        .status(200)
        .json('User has been logged out.');
};

auth.routes.js

const express = require('express');
const router = express.Router();

const { register, login, logout } = require('../controllers/auth.js');

router.post('/register', register);
router.post('/login', login);
router.post('/logout', logout);

module.exports = router;

在前端,我使用了React的Context API。
api.js

export const handleLogin = async (
    e,
    values,
    setError,
    navigate,
    path,
    login
) => {
    e.preventDefault();

    try {
        await login(values);
        navigate(path);
    } catch (err) {
        console.log(err);
        setError(err);
    }
};

authContext.js

const AuthContextProvider = ({ children }) => {
    const [currentUser, setCurrentUser] = useState(
        JSON.parse(localStorage.getItem('user')) || null
    );

    const login = async values => {
        const result = await axios.post(
            'https://api.example.url/api/auth/login',
            values,
            { withCredentials: true }
        );
        setCurrentUser(result.data);
    };

    const logout = async () => {
        await axios.post(
            'https://api.example.url/api/auth/logout',
            {},
            { withCredentials: true }
        );
        setCurrentUser(null);
    };

    useEffect(() => {
        localStorage.setItem('user', JSON.stringify(currentUser));
    }, [currentUser]);

    return (
        <AuthContext.Provider value={{ currentUser, login, logout }}>
            {children}
        </AuthContext.Provider>
    );
};

export default AuthContextProvider;

LoginForm.js

const LoginForm = () => {
    const [inputs, setInputs] = useState({
        username: '',
        password: ''
    });

    const { login } = useContext(AuthContext);

    const [error, setError] = useState(null);

    const navigate = useNavigate();

    return (
        <form className={styles.form}>
            <div className={styles.wrapper}>
                <input
                    name='username'
                    type='text'
                    placeholder='Username'
                    onChange={e => handleChange(e, setInputs)}
                />
                <input
                    name='password'
                    type='password'
                    placeholder='Password'
                    onChange={e => handleChange(e, setInputs)}
                />
            </div>

            {error && <span className={styles.error}>{error.response.data}</span>}

            <button
                className={styles.button}
                type='submit'
                onClick={e => handleLogin(e, inputs, setError, navigate, '/', login)}>
                Login
            </button>

... Additional code...

此外,当用户登录时,它不会显示CORS策略错误或类似的错误,它只是像往常一样继续使用应用程序:/并正常设置本地存储,没有问题。

tzxcd3kk

tzxcd3kk1#

我现在能够修复它,问题是我没有指定(或错误指定)cookie中的“sameSite”属性。此外,我没有指定其他Axios请求必须使用必要的凭据,使用“withCredentials”属性,这样当他们必须使用cookie时就不会出错。
这是代码现在的样子:
auth.js

res
    .cookie('access_token', token, {
                httpOnly: true,
                sameSite: 'none',
                secure: true
    })
    .status(200)
    .json(other);

res
    .clearCookie('access_token', {
        httpOnly: true,
        sameSite: 'none',
        secure: true
    })
    .status(200)
    .json('User has been logged out.');

Axios在前端请求:
authContext.js

await axios.post(
            'api.example.com/api/auth/login',
            {value1: 'hello', value2: 'bye'},
            { withCredentials: true }
);

await axios.post(
            'api.example.com/api/auth/logout',
            {},
            { withCredentials: true }
);

相关问题