繁体   English   中英

发送 Axios GET 请求时报错 401 Unauthorized

[英]Error 401 Unauthorized when sending Axios GET request

我正在使用 ReactJS 项目使用 axios 从 MongoDB 获取数据。

我有一个调用 startLogin function 的登录组件,总的来说有两个 axios 请求让我登录应用程序,一个发送用户数据的 POST 请求和一个访问用户信息的 GET 请求。 POST 请求在 200 状态代码下工作正常,但出于某种原因,GET 请求以 401 错误代码响应。 我的后端项目 API Rest 在服务器 187:3000 上工作,当我尝试从外部来源向后端服务器发送请求时,前端项目失败,我的意思是,如果我在同一台服务器上使用 React 项目API 正在运行,没有问题,但是当我想从其他服务器或本地主机执行此操作时,情况就不同了。

这是我的 API 路线代码:

索引.js

const path = require("path");
const express = require("express");
const authRouter = require("./authRouter");
const apiRouter = require("./apiRouter");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const auth = require("../middleware/auth");
const {
  changeSubscriptionStatus,
} = require("../controllers/subscriptionController");
const mtto = false;

module.exports = function (app) {
  //SOLUCION CORS
  app.use(function (req, res, next) {
    // Website you wish to allow to connect

    res.setHeader("Access-Control-Allow-Origin", "http://10.10.251.194:5173");

    // Request methods you wish to allow
    res.setHeader(
      "Access-Control-Allow-Methods",
      "GET, POST, PUT, PATCH, DELETE"
    );

    // Request headers you wish to allow
    res.setHeader(
      "Access-Control-Allow-Headers",
      "Origin, X-Requested-With, Accept, Content-Type, Access-Control-Request-Method, Authorization, X-Auth-Token, Cookie"
    );

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader("Access-Control-Allow-Credentials", true);

    // Pass to next layer of middleware
    next();
  });
app.use(bodyParser.json({ limit: "100kb" }));
  app.use(cookieParser());
  app.use("/auth", authRouter);
  app.use("/api", apiRouter);

  // routing static assets from build
  app.use(
    express.static(path.resolve(__dirname, "../../build"), {
      index: false,
    })
  );

  // webpack hot reloading hack
  if (process.env.NODE_ENV === "hot") {
    const webpack = require("webpack");
    const webpackConfig = require("../../webpack.config");
    const compiler = webpack(webpackConfig);

    app.use(
      require("webpack-dev-middleware")(compiler, {
        noInfo: true,
        publicPath: webpackConfig.output.publicPath,
      })
    );
    app.use(require("webpack-hot-middleware")(compiler));
  }

  app.post("/transactions/pending", changeSubscriptionStatus);

  app.get("*", auth.optionalJwt, function (req, res, next) {
    // console.log(req.originalUrl)
    if (mtto)
      return res.sendFile(path.resolve(__dirname, "../../mtto/index.html"));
    if (req.user) {
      return res.sendFile(
        path.resolve(__dirname, "../../build/dashboard/index.html")
      );
    }
    return res.sendFile(
      path.resolve(__dirname, "../../build/public/index.html")
    );
  });
};

authRouter.js

const express = require("express");
const authRouter = express.Router();
const authController = require("../controllers/authController");
const apiErrorHandler = require("../middleware/apiErrorHandler");
const auth = require("../middleware/auth");

authRouter.get("/", auth.jwt, authController.userInfo);
authRouter.post("/", authController.login);
authRouter.put("/", authController.resetPassword);
authRouter.delete("/", auth.jwt, authController.logout);
authRouter.put("/profile", auth.jwt, authController.editUser);
authRouter.get("/logout", authController.logout);
authRouter.post(
  "/users",
  authController.validateRegister,
  authController.register
);
authRouter.post("/recover", authController.recover);
authRouter.put("/password", auth.jwt, authController.changePassword);
authRouter.post(
  "/invite",
  authController.validateRegister,
  authController.registerWithInvite
);
authRouter.post("/verification", authController.resendVerification);
authRouter.post("/verification/:token", authController.verify);

authRouter.use(apiErrorHandler);

module.exports = authRouter;`

authController.js

const passport = require("passport");
const ApiError = require("../util/ApiError");
const validator = require("validator");
const User = require("../models/user");
const notMissing = require("../util/notMissing");
const jwt = require("jsonwebtoken");

const login = (req, res, next) => {
  passport.authenticate("local", (err, user, info) => {
    if (err) return next(err);
    if (!user) return next(info);
    res.cookie("jwt", user.jwtToken());
    let accounts = { 30: "invited", 40: "admin", 100: "sysadmin" }; //solis
    User.findByIdAndUpdate(
      { _id: user.id },
      { $set: { last_login: new Date() } }
    ).then();
    res.json({
      ok: true,
      typeAccount: accounts[user.position],
      token: user.jwtToken(),
    });
  })(req, res, next);
};

const logout = (req, res, next) => {
  res.cookie("jwt", "");
  res.json({ ok: true });
};

const validateRegister = (req, res, next) => {
  let data = req.body.data || req.body;
  data.name = data.name ? data.name.trim() : "";
  // Start validating
  if (!data.name) return next(new ApiError(400, "Ingresa tu nombre completo"));
  if (!data.password) return next(new ApiError(400, "Ingresa tu contraseña"));
  if (!data.confirm)
    return next(new ApiError(400, "Ingresa la confirmación de tu contraseña"));
  if (data.password !== data.confirm)
    return next(
      new ApiError(400, "La contraseña y la confirmación no coinciden")
    );
  if (data.password.length < 8)
    return next(
      new ApiError(400, "La contraseña debe incluir mínimo 8 caracteres")
    );
  next();
};

const register = (req, res, next) => {
  req.body.email = req.body.email ? req.body.email.toLowerCase().trim() : "";
  if (!req.body.email)
    return next(new ApiError(400, "Ingresa tu correo electrónico"));
  if (!validator.isEmail(req.body.email))
    return next(
      new ApiError(400, "La dirección de correo electrónico no es válida")
    );
  User.register(req.body)
    .then((user) => res.json({ ok: true }))
    .catch(next);
};

const recover = (req, res, next) => {
  if (!req.body.email)
    return next(new ApiError(400, "Ingresa tu correo electrónico"));
  let user;
  User.findOne({ email: req.body.email })
    .then((foundUser) => {
      if (!foundUser)
        return Promise.reject(
          new ApiError(
            404,
            `No hay un usuario registrado con el correo ${req.body.email}`
          )
        );
      user = foundUser;
      return user.generateRecoveryToken();
    })
    .then((token) => user.sendRecoveryEmail(token))
    .then((_) => res.json({ ok: true }))
    .catch(next);
};

const resetPassword = (req, res, next) => {
  if (!req.body.token)
    return next(new ApiError(400, "No se encontró el token"));
  if (!req.body.password)
    return next(new ApiError(400, "Ingresa tu nueva constraseña"));
  if (!req.body.confirm)
    return next(new ApiError(400, "Confirma tu nueva contraseña"));
  if (req.body.password !== req.body.confirm)
    return next(
      new ApiError(400, "La contraseña y la confirmación no coinciden")
    );
  let user;
  let now = new Date();
  User.findOne({
    "recovery_token.token": req.body.token,
    "recovery_token.expires_at": { $gt: now },
  })
    .then((foundUser) => {
      if (!foundUser)
        return Promise.reject(
          new ApiError(
            404,
            `El token es inválido o ya ha expirado. Intenta nuevamente.`
          )
        );
      user = foundUser;
      return user.changePassword(req.body.password);
    })
    .then((_) => res.json({ ok: true }))
    .catch(next);
};

const changePassword = (req, res, next) => {
  if (!req.body.current_password)
    return next(new ApiError(400, "Ingresa tu contraseña anterior"));
  if (!req.body.new_password)
    return next(new ApiError(400, "Ingresa tu nueva contraseña"));
  if (!req.body.confirm)
    return next(new ApiError(400, "Confirma tu nueva contraseña"));
  if (req.body.new_password !== req.body.confirm)
    return next(
      new ApiError(400, "La contraseña y la confirmación no coinciden")
    );
  req.user
    .isValidPassword(req.body.current_password)
    .then((isValid) => {
      if (!isValid)
        return Promise.reject(
          new ApiError(403, "La contraseña anterior es incorrecta")
        );
      return req.user.changePassword(req.body.new_password);
    })
    .then((_) => res.json({ ok: true }))
    .catch(next);
};

const userInfo = (req, res, next) => {
  res.json(req.user);
};

const editUser = (req, res, next) => {
  req.user.name = req.body.name;
  return req.user
    .save()
    .then((user) => res.json(user))
    .catch(next);
};

const registerWithInvite = (req, res, next) => {
  notMissing(req.body, [
    "token",
    "data",
    "data.name",
    "data.password",
    "data.confirm",
  ])
    .then((_) => User.registerWithInvite(req.body.token, req.body.data))
    .then((user) => {
      res.cookie("jwt", user.jwtToken());
      res.json(user);
    })
    .catch(next);
};

const verify = (req, res, next) => {
  let now = new Date();
  User.findOne({
    "verification_token.token": req.params.token,
    "verification_token.expires_at": { $gt: now },
  })
    .then((user) => {
      if (!user)
        return Promise.reject(
          new ApiError(
            404,
            "El enlace de verificación es inválido o ya ha expirado. Intenta iniciar sesión nuevamente para solicitar el reenvío."
          )
        );
      user.is_verified = true;
      return user.save();
    })
    .then((user) => {
      res.cookie("jwt", user.jwtToken());
      return res.json({ ok: true });
    })
    .catch(next);
};

const resendVerification = (req, res, next) => {
  notMissing(req.body, ["email"])
    .then((_) =>
      User.findOne({ email: req.body.email, is_verified: { $ne: true } })
    )
    .then((user) => {
      if (!user)
        return Promise.reject(
          new ApiError(
            404,
            "El usuario ya está verificado o no está registrado con ese correo electrónico."
          )
        );
      return Promise.all([user, user.renewVerificationToken()]);
    })
    .then(([user, token]) => user.sendVerificationEmail(token))
    .then((_) => res.json({ ok: true }))
    .catch(next);
};

const authController = {
  login,
  logout,
  register,
  validateRegister,
  registerWithInvite,
  recover,
  resetPassword,
  changePassword,
  userInfo,
  editUser,
  verify,
  resendVerification,
};

module.exports = authController;

auth.js

    const passport = require("passport");
    const ApiError = require("../util/ApiError");
    const { CompanyStatus } = require("../constants/enums");
    
    function isAuthenticated(req, res, next) {
      console.log(req);
      if (req.isAuthenticated()) return next();
      next(new ApiError(401, "Unauthenticated"));
    }
    
    function optionalJwt(req, res, next) {
      if (req.cookies && req.cookies.jwt) {
        return passport.authenticate(
          "jwt",
          { session: false },
          (err, user, info) => {
            if (err) return next(err);
            req.user = user;
            return next();
          }
        )(req, res, next);
      }
      return next();
    }
    
    function hasPosition(position) {
      return (req, res, next) => {
        if (req.user.position < position) {
          return next(ApiError.Forbidden("Permisos insuficientes"));
        }
        next();
      };
    }
    
    function belongsToCompanyWithPosition(position = 0) {
      return (req, res, next) => {
        if (
          req.user.company.id !== req.params.companyId ||
          req.user.position < position
        ) {
          return next(ApiError.Forbidden("Permisos insuficientes"));
        }
        next();
      };
    }
    
    function companyIsActive(req, res, next) {
      if (req.user.company.status !== CompanyStatus.ACTIVE) {
        return next(ApiError.Forbidden("Tu cuenta está desactivada"));
      }
      next();
    }
    
    module.exports = {
      jwt: passport.authenticate("jwt", { session: false }),
      isAuthenticated,
      optionalJwt,
      hasPosition,
      belongsToCompanyWithPosition,
      companyIsActive,
    };

这是我的前台代码:

ctCloudApi.js

import axios from "axios";

let url = "http://10.10.251.187:3000";

const ctCloudApi = axios.create({
  baseURL: url,
  withCredentials: true,
});

使用AuthStore.js

import { useDispatch, useSelector } from "react-redux";
import { ctCloudApi } from "../apis";
import {
  onChecking,
  onLogin,
} from "../redux";

export const useAuthStore = () => {
const dispatch = useDispatch();

const startLogin = async ({ email, password }) => {
    try {
      // Se llama a la api
      const resp = await ctCloudApi.post("/auth", { email, password });
      console.log(resp);
      const token = resp.data.token;
      if (resp.data.ok) {
        dispatch(onChecking()); // Se llama a la accion para volver todos los estados por defecto
        const resp = await ctCloudApi.get(`/auth`, {
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`,
          },
        });
        if (resp.status === 200) {
          dispatch(onLogin(resp.data));
          return;
        }
      }
    } catch (error) {
      dispatch(
        setMessage({
          type: "login",
          msg: error.message,
        })
      );
      setTimeout(() => {
        dispatch(clearMessage());
      }, 2000);
      return;
    }
  };

这是我收到的错误消息: 在此处输入图像描述

这些是发送的 axios 请求及其响应: 在此处输入图像描述 在此处输入图像描述

我正在尝试使用 axios 与 API 通信,我得到 401 状态码

你能为 cookie 设置设置它并检查它是如何 go:

  const login = (req, res, next) => {
  passport.authenticate("local", (err, user, info) => {
    if (err) return next(err);
    if (!user) return next(info);
    res.cookie("jwt", user.jwtToken(),{
      maxAge: 30000, // 30 sec to test
      httpOnly: true,
      secure: true, // only for https
      sameSite: "none"  // false or lax for development
  });
    let accounts = { 30: "invited", 40: "admin", 100: "sysadmin" }; //solis
    User.findByIdAndUpdate(
      { _id: user.id },
      { $set: { last_login: new Date() } }
    ).then();
    res.json({
      ok: true,
      typeAccount: accounts[user.position],
      token: user.jwtToken(),
    });
  })(req, res, next);
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM