由于CORS的限制,无法在Express和React应用之间进行数据获取。

16 浏览
0 Comments

由于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 (
      

Login Below!

); } }

\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如果提供的信息太多,请谅解,我已经困扰了很长时间,真的不知道还能做什么了。

0
0 Comments

解决方法:安装cors模块,然后在server.js文件中添加以下代码:

const cors = require('cors');
app.use(cors());

出现原因:由于CORS(跨域资源共享)限制,Express和React应用程序之间无法进行数据获取。

0
0 Comments

Express和React应用程序之间无法进行数据获取的原因是CORS(跨源资源共享)问题。CORS是一种用于控制不同源(域、协议、端口)之间的请求和响应的机制。当浏览器发出跨域请求时,如果服务器没有正确配置CORS,就会出现该问题。

上述代码中,通过在Express应用程序中添加app.use(cors());来解决CORS问题。这一行代码的作用是在所有路由处理函数之前使用CORS中间件。此外,在res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');中设置允许连接的来源为'http://localhost:8080'。

需要注意的是,Express应用程序会按照添加的顺序依次执行中间件函数,因此中间件函数的顺序很重要。

希望这样能解决你的问题。如果还有其他疑问,请随时提问。

0
0 Comments

问题出现的原因是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应用程序的地址。然而,仍然会出现错误,可能是由于后端出现问题导致的。

0