由于 CORS,无法在 Express 和 React 应用程序之间获取

Nan*_*ins 2 proxy fetch node.js express reactjs

我的应用程序运行良好,我能够在 Express 和 React 服务器之间获取数据。我重新组织了我的代码,现在我无法摆脱 CORS 错误并且根本无法获取任何数据。我无法继续我的项目,根本无法自己弄清楚,我真的尝试过。

前端工作正常,直到我尝试登录,然后身份验证失败

我已尝试添加标头并已将 CORS 安装到我的 Express 应用程序中。我在我的 react package.json 中为 express URL 指定了一个代理。

  • 这是我的 Express server.js
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) {
  // Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

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

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

// 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(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)

// mongoose.connection.once('open', run);

app.listen(process.env.PORT || 8080);
console.log('Server is listening on port ' + process.env.PORT);
Run Code Online (Sandbox Code Playgroud)
  • 这是我的用户控制器
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 {
            // Issue 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
}
Run Code Online (Sandbox Code Playgroud)
  • 这是我的用户路线
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
Run Code Online (Sandbox Code Playgroud)
  • 这是一个检查令牌的中间件函数,这是错误似乎指向的地方,但我确定它实际上与代理和获取被 CORS 阻止有关。
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;
Run Code Online (Sandbox Code Playgroud)
  • 这是我的身份验证组件,其中错误也指向
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';


//withAuth is a high-order component which takes in a component to protect 
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 <Redirect to="/login" />;
      }
      return (
        <React.Fragment>
          <ComponentToProtect {...this.props} />
        </React.Fragment>
      );
    }
  }
}
Run Code Online (Sandbox Code Playgroud)
  • 登录组件
import React, { Component } from 'react';

export default class Login extends Component { //impplicit vs explicit returns
  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 (
      <form onSubmit={this.onSubmit}>
        <h1>Login Below!</h1>
        <input
          type="email"
          name="email"
          placeholder="Enter email"
          value={this.state.username}
          onChange={this.handleInputChange}
          required
        />
        <input
          type="password"
          name="password"
          placeholder="Enter password"
          value={this.state.password}
          onChange={this.handleInputChange}
          required
        />
        <input type="submit" value="Submit"/>
      </form>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这是主要错误:

从源“ http://localhost:3000 ”获取“ http://localhost:8080/api/checktoken ”的访问已被 CORS 策略阻止:“Access-Control-Allow-Origin”标头具有值“ http://localhost:8080 ' 不等于提供的来源。让服务器发送带有有效值的标头,或者,如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。

它还说:

withAuth.jsx:17 GET http://localhost:8080/api/checktoken net::ERR_ABORTED 401(未授权)

在我的快递应用程序中,终端说它无法读取中间件中的令牌,我认为这也是由于 cors :

类型错误:无法在 withAuth 处读取未定义的属性“令牌”(/Users/nancycollins/virtuload-beta/backend/middleware.js:6:16)

抱歉,如果这是太多信息,我只是被困在这个问题上太久了,真的不知道还能做什么。

sig*_*mus 5

更新:

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

和:

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');