NodeJS 客户端不接收或保存头中的身份验证cookie(服务器和客户端托管在不同的域上)

wgxvkvu9  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(95)

我有一个简单的任务管理应用程序,客户端是用REACT做的,后端是用NODE JS做的。它有一个简单的登录,从服务器生成一个令牌,作为cookie发送给客户端(使用json web令牌),客户端接收它并将其存储在头部(使用js-cookie)。本地一切正常,问题是当我在不同的域上托管它们时,客户端托管在www.example.com上Netlify.app,服务器托管在Render.com上。当请求用户的身份验证cookie(令牌)时,它失败并返回一个错误,告诉我令牌无效并拒绝我访问:消息:“无效令牌,访问被拒绝”.

import { TOKEN_SECRET } from "../config.js";
import jwt from "jsonwebtoken";

export const authRequired = (req, res, next) => {
  const { token } = req.cookies;

  if (!token)
    return res.status(401).json({ Mensaje: "Token invalido, Acceso denegado" });

  jwt.verify(token, TOKEN_SECRET, (err, user) => {
    if (err) return res.status(403).json({ mensaje: "token invalido" });

    req.user = user;
    next();
  });
};

我的jwt.js:

import jwt from "jsonwebtoken";
import { TOKEN_SECRET } from "../config.js";

export function createAccessToken(payload) {
  return new Promise((res, rej) => {
    jwt.sign(payload, TOKEN_SECRET, { expiresIn: "1d" }, (err, token) => {
      if (err) rej(err);
      res(token);
    });
  });
}

来自客户:AuthContext.jsx:

import { createContext, useContext, useState, useEffect } from "react";
import Cookies from "js-cookie";
import {
  registerRequest,
  loginRequest,
  verifyTokenRequest,
} from "../api/auth.js";

export const AuthContext = createContext();

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("El useAuth debe ser usado con un AuthProvider");
  }
  return context;
};

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [FormErrors, setFormErrors] = useState([]);
  const [loading, setLoading] = useState(true);

  const signup = async (user) => {
    try {
      const res = await registerRequest(user);
      setUser(res.data);
      setIsAuthenticated(true);
    } catch (error) {
      if (Array.isArray(error.response.data)) {
        setFormErrors(error.response.data);
      }
      setFormErrors(error.response.data);
      console.log(error.response.data);
    }
  };

  const signin = async (user) => {
    try {
      const res = await loginRequest(user);
      setUser(res.data);
      setIsAuthenticated(true);
    } catch (error) {
      if (Array.isArray(error.response.data)) {
        setFormErrors(error.response.data);
      }
      setFormErrors(error.response.data);
      console.log(error.response.data);
    }
  };

  const logout = () => {
    Cookies.remove("token");
    setIsAuthenticated(false);
    setUser(null);
  };

  useEffect(() => {
    if (FormErrors.length > 0) {
      const timer = setTimeout(() => {
        setFormErrors([]);
      }, 10000);
      return () => clearTimeout(timer);
    }
  }, [FormErrors]);

  useEffect(() => {
    async function checkLogin() {
      const jCookies = Cookies.get();

      if (!jCookies.token) {
        setIsAuthenticated(false);
        setLoading(false);
        return setUser(null);
      }
      try {
        const res = await verifyTokenRequest(jCookies.token);
        if (!res.data) {
          setIsAuthenticated(false);
          setLoading(false);
          return;
        }

        setIsAuthenticated(true);
        setUser(res.data);
        setLoading(false);
      } catch (error) {
        setIsAuthenticated(false);
        setUser(null);
        setLoading(false);
      }
    }
    checkLogin();
  }, []);

  return (
    <AuthContext.Provider
      value={{
        signup,
        signin,
        logout,
        user,
        isAuthenticated,
        FormErrors,
        loading,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

Axios授权人:

import axios from "./axios.js";

export const registerRequest = (user) => axios.post(`/register`, user);

export const loginRequest = (user) => axios.post(`/login`, user);

export const verifyTokenRequest = () => axios.get("/verify");

Axios示例:

import axios from "axios";

const instance = axios.create({
  baseURL: "https://exampleurl.com/api"
  withCredentials: true,
});

export default instance;

稍微调查一下,我只读到为了避免这个问题,我必须在同一个域上托管服务器和客户端。然而,这只是一个实践项目,我不想花钱在VPS或托管。另一种解决方案是使用代理,但我不知道如何配置代理。我还能做些什么来让客户端将令牌存储为cookie,而不必将服务器或客户端从它们托管的位置移动,或者我必须为此付费吗?
PD:这是我第一个使用Node js和REACT的项目

gwbalxhn

gwbalxhn1#

我不知道如果没有自定义域设置这是可能的-你不能设置一个cookie的域是一个不同的域。例如,myapp.netlify.com无法为mybackend.onrender.com设置Cookie。
如果你不是100%依赖netlify,那么在render上托管你的react应用和你的应用是很容易的(而且是免费的)。这样,您就可以使用Cookie,因为这两个应用程序将位于onrender.com的同一个根域中

相关问题