[英]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 与 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.