由于CORS的限制,无法在Express和React应用之间进行数据获取。
由于CORS的限制,无法在Express和React应用之间进行数据获取。
我的应用程序之前工作正常,我能够在我的Express和React服务器之间获取数据。我重新组织了我的代码,现在无法解决CORS错误,并且无法获取任何数据。我无法继续进行我的项目,也无法自己弄清楚,我真的尽力了。\n前端在尝试登录之前工作正常,然后身份验证失败。\n我尝试添加头文件并在我的Express应用程序中安装CORS。我在我的react package.json中指定了一个代理到express URL。\n这是我的Express server.js:\n
const express = require('express'); const bodyParser = require('body-parser'); const cookieParser = require('cookie-parser'); const path = require('path'); const cors = require('cors'); const methodOverride = require('method-override'); const db = require('./db/index.js') db.on('error', console.error.bind(console, 'MongoDB connection error:')) require('dotenv').config(); const app = express(); app.disable('x-powered-by'); app.use(function(req, res, next) { // 允许连接的网站 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080'); // 允许的请求方法 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // 允许的请求头 res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // 如果需要网站在请求中包含Cookies,设置为true res.setHeader('Access-Control-Allow-Credentials', true); // 传递给下一个中间件 next(); }); app.use(methodOverride('_method')); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(cookieParser()); app.use(cors({ origin: 'http://localhost:8080' })); app.use(express.static(path.join(__dirname, '../build'))); app.get('/', function (req, res) { res.sendFile(path.join(__dirname, '../build', 'index.html')); }); const userRouter = require('./routes/user-routes') app.use('/api', userRouter) const fileRouter = require('./routes/file-routes') app.use('/file', fileRouter) app.listen(process.env.PORT || 8080); console.log('Server is listening on port ' + process.env.PORT);
\n这是我的用户控制器:\n
const User = require('../models/Users'); const secretShh = 'mysecretsshhh'; const jwt = require('jsonwebtoken'); const home = (req, res) => { res.send('Welcome!'); }; const secret = (req, res) => { res.send('The password is potato'); }; const register = (req, res) => { const { email, password } = req.body; const user = new User({ email, password }); user.save(function(err) { if (err) { console.log(err); res.status(500).send("Error registering new user please try again."); } else { res.status(200).send("Welcome to the club!"); } }); }; const authenticate = (req, res) => { const { email, password } = req.body; User.findOne({ email }, function(err, user) { if (err) { console.error(err); res.status(500) .json({ error: 'Internal error please try again' }); } else if (!user) { res.status(401) .json({ error: 'Incorrect email or password' }); } else { user.isCorrectPassword(password, function(err, same) { if (err) { res.status(500) .json({ error: 'Internal error please try again' }); } else if (!same) { res.status(401) .json({ error: 'Incorrect email or password' }); } else { // 生成token const payload = { email }; const token = jwt.sign(payload, secretShh, { expiresIn: '1h' }); res.cookie('token', token, { httpOnly: true }).sendStatus(200); } }); } }); }; const token = (req, res) => { res.sendStatus(200); }; module.exports = { home, secret, register, authenticate, token }
\n这是我的用户路由:\n
const express = require('express') const UserCtrl = require('../controllers/user-ctrl') const withAuth = require('../middleware'); const router = express.Router() router.get('/home', UserCtrl.home) router.get('/secret', withAuth, UserCtrl.secret) router.post('/register', UserCtrl.register) router.post('/authenticate', UserCtrl.authenticate) router.get('/checktoken', withAuth, UserCtrl.token) module.exports = router
\n这是用于检查token的中间件函数,错误似乎指向这里,但我确信实际上是与代理和CORS阻止fetch有关:\n
const jwt = require('jsonwebtoken'); const secret = 'mysecretsshhh'; const withAuth = (req, res, next) => { const token = req.body.token || req.query.token || req.headers['x-access-token'] || req.cookies.token; if (!token) { res.status(401).send('Unauthorized: No token provided'); } else { jwt.verify(token, secret, function(err, decoded) { if (err) { res.status(401).send('Unauthorized: Invalid token'); } else { req.email = decoded.email; next(); } }); } } module.exports = withAuth;
\n这是我的auth组件,错误也指向这里:\n
import React, { Component } from 'react'; import { Redirect } from 'react-router-dom'; export default function withAuth(ComponentToProtect) { return class extends Component { constructor() { super(); this.state = { loading: true, redirect: false, }; } async componentDidMount() { fetch('http://localhost:8080/api/checktoken', { credentials: 'include', mode: 'cors' }) .then(res => { if (res.status === 200) { this.setState({ loading: false }); } else { const error = new Error(res.error); throw error; } }) .catch(err => { console.error(err); this.setState({ loading: false, redirect: true }); }); } render() { const { loading, redirect } = this.state; if (loading) { return null; } if (redirect) { return; } return ( ); } } }
\n这是登录组件:\n
import React, { Component } from 'react'; export default class Login extends Component { constructor(props) { super(props) this.state = { email : '', password: '' }; } handleInputChange = (event) => { const { value, name } = event.target; this.setState({ [name]: value }); } onSubmit = async (event) => { event.preventDefault(); fetch('/api/authenticate', { method: 'POST', body: JSON.stringify(this.state), headers: { 'Content-Type': 'application/json' } }) .then(res => { if (res.status === 200) { this.props.history.push('/'); } else { const error = new Error(res.error); throw error; } }) .catch(err => { console.error(err); alert('Error logging in please try again'); }); } render() { return (); } }
\n主要错误是:\nAccess to fetch at \'http://localhost:8080/api/checktoken\' from origin \'http://localhost:3000\' has been blocked by CORS policy: The \'Access-Control-Allow-Origin\' header has a value \'http://localhost:8080\' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request\'s mode to \'no-cors\' to fetch the resource with CORS disabled.\n还有:\nwithAuth.jsx:17 GET http://localhost:8080/api/checktoken net::ERR_ABORTED 401 (Unauthorized)\n在我的Express应用程序中,终端说无法在中间件中读取令牌,我认为这也是由于CORS引起的:\nTypeError: Cannot read property \'token\' of undefined\n at withAuth (/Users/nancycollins/virtuload-beta/backend/middleware.js:6:16)\n如果提供的信息太多,请谅解,我已经困扰了很长时间,真的不知道还能做什么了。
Express和React应用程序之间无法进行数据获取的原因是CORS(跨源资源共享)问题。CORS是一种用于控制不同源(域、协议、端口)之间的请求和响应的机制。当浏览器发出跨域请求时,如果服务器没有正确配置CORS,就会出现该问题。
上述代码中,通过在Express应用程序中添加app.use(cors());
来解决CORS问题。这一行代码的作用是在所有路由处理函数之前使用CORS中间件。此外,在res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
中设置允许连接的来源为'http://localhost:8080'。
需要注意的是,Express应用程序会按照添加的顺序依次执行中间件函数,因此中间件函数的顺序很重要。
希望这样能解决你的问题。如果还有其他疑问,请随时提问。
问题出现的原因是CORS(跨源资源共享)问题。解决方法是在Express应用程序中设置访问控制头部,将允许访问的源改为React应用程序的地址。
具体来说,原先的设置是将访问控制头部的"Access-Control-Allow-Origin"属性设置为"http://localhost:8080",需要将其改为"http://localhost:3000"。但是,即使进行了这样的更改,仍然会出现错误。
错误的具体表现是,浏览器控制台中显示多个错误信息,包括"Failed to load resource: the server responded with a status of 500 (Internal Server Error)"和"GET localhost:3003/api/checktoken 500 (Internal Server Error)"等。还有一些与favicon相关的错误信息。
有人猜测这可能与开发模式有关,因为React控制台中显示了一条提示信息:"Note that the development build is not optimized. To create a production build, use npm run build."但是,该用户希望处于开发模式,而不是生产模式。
另一位用户指出,错误500可能是后端出现问题导致的,而不是开发模式的问题。但是,该用户通过Postman测试后端时一切正常。
该问题的出现是因为CORS问题,解决方法是在Express应用程序中设置访问控制头部,将允许访问的源改为React应用程序的地址。然而,仍然会出现错误,可能是由于后端出现问题导致的。