Postman中API正常,React前端调用登录接口遇连接拒绝错误
我的接口在Postman中能正常调用,但在React网站里无法使用。我用Axios和React开发了认证功能,后端运行在3005端口,前端运行在3000端口。所有API在Postman里都没问题,但前端调用登录接口时出现错误:xhr.js:244 POST http://192.168.1.147/api/auth/login net::ERR_CONNECTION_REFUSED
后端登录认证控制器代码
exports.login = async (req, res, next) => { const { email, password } = req.body; if(!email || !password){ return next(new ErrorResponse("Introduceti email sau parola valida", 400)) } try{ const user = await User.findOne ({ email }).select("+password"); if(!user){ return next(new ErrorResponse("Credentiale nevalide", 401)) } const isMatch = await user.matchPasswords(password); if(!isMatch){ return next(new ErrorResponse("Credentiale nevalide", 401)) } sendToken(user, 200, res); }catch(error) { res.status(500).json({ succes: false, error: error.message }) } };
React登录页面代码
import React from "react"; import { Navbar } from "../components/Navbar"; import { Footer } from './sections/Footer'; import RegisterIMG from '../assets/register.svg'; import axios from 'axios'; import { useState, useEffect } from 'react'; export const Login = ({ history }) => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); useEffect(() => { if(localStorage.getItem("authToken")){ history.push("/"); } }, [history]); const loginHandler = async (e) => { e.preventDefault(); const config = { header: { "Content-Type": "application/json" } } try { const {data} = await axios.post("http://192.168.1.147/api/auth/login" , { email, password }, config); localStorage.setItem("authToken", data.token); history.push("/"); } catch (error) { setError(error.response.data.error); setTimeout(() => { setError(""); }, 5000); } } return ( <> <Navbar></Navbar> <div className="login-container"> <div className="login-left"> <div className="login-header"> <h1>Conecteaza-te</h1> <p>Introduceti datele pentru logare</p> {error && <span className="error-message">{error}</span>} </div> <form className="login-form" onSubmit={loginHandler}> <div className="login-form-content"> <div className="form-item"> <label /*for="emailForm"*/ htmlFor="email">Intruduceti email</label> <input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} tabIndex={1} required /> </div> <div className="form-item"> <label /*for="passwordForm"*/ htmlFor="password">Introduceti parola</label> <input type="password" id="password" required value={password} onChange={(e) => setPassword(e.target.value)} tabIndex={2} /> </div> <button type="submit" className="loginSubmit" tabIndex={3}>Conecteaza-te</button> </div> <div className="login-form-footer"> <p>Nu ai cont?<a href="/register">Creeaza acum unul!</a></p> <p><a href="/forgotpassword">Ai uitat parola?</a></p> </div> </form> </div> <div className="login-right"> <img src={ RegisterIMG } alt="image" /> </div> </div> <Footer></Footer> </> ); };
补全请求地址的端口号:后端运行在3005端口,但前端请求地址未携带端口,需将
http://192.168.1.147/api/auth/login改为http://192.168.1.147:3005/api/auth/login。Postman能正常调用是因为手动指定了端口,前端代码遗漏该配置。配置后端跨域(CORS):前后端端口不同会触发浏览器跨域限制,需在后端添加CORS支持。以Express框架为例,安装
cors包后添加中间件:const cors = require('cors'); // 允许所有来源(开发环境可用) app.use(cors()); // 或严格指定允许的前端地址 app.use(cors({ origin: 'http://localhost:3000' }));验证后端服务状态:确认后端服务确实在
192.168.1.147:3005运行,端口未被防火墙或其他进程占用。可在终端执行curl http://192.168.1.147:3005/api/auth/login测试连通性。前端配置代理(可选):避免代码中写死后端地址,可在React项目的
package.json中添加代理配置:"proxy": "http://192.168.1.147:3005"之后前端请求可简化为
axios.post("/api/auth/login", { email, password }, config),开发环境下会自动转发到后端地址。
内容的提问来源于stack exchange,提问作者crazvan

