OPTIONS预检请求后,Node + Express服务器没有响应

时间:2018-02-20 01:22:25

标签: node.js express cors passport.js

我目前面临以下错误,我在节点js中开发了一个API,让我们说虚拟商店。用于在购物车中获取其商品的用户需要进行身份验证。正在通过JWT处理身份验证,我正在使用护照模块。

对于需要身份验证的路由,使用'身份验证'标题与其通讯员JWT ey ......'令牌,服务器不处理任何请求。只需响应OPTIONS预检请求,仅此而已。 我尝试使用httpClient从角度前端使用/ api / cart,以及授权标头并在chrome devTools中获得以下错误

chrome console log

我也尝试使用邮递员,发送授权标题并且无法获得任何响应屏幕。

我正在记录OPTIONS请求标头。以下是使用授权标头命中/ api / cart后的服务器响应,它停在那里。

 !OPTIONS
    { host: 'localhost:3000',
      connection: 'keep-alive',
      'access-control-request-method': 'GET',
      origin: 'http://localhost:4200',
      'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36',
      'access-control-request-headers': 'authorization,content-type',
      accept: '*/*',
      'accept-encoding': 'gzip, deflate, br',
      'accept-language': 'en-US,en;q=0.9' }
    !OPTIONS
    OPTIONS /api/cart 200 1.288 ms - -

server.js

    const mongoose = require("mongoose");
    const express = require("express");
    const bodyParser = require("body-parser");
    const morgan = require("morgan");
    const passport = require("passport");
    const config = require("./config/database"); //Getting databas config file
    const User = require("./app/models/user"); //we're getting mongoose model
    const Product = require("./app/models/product");

    const app = express();
    const port = process.env.PORT || 3000;
    const routes = require("./app/routes/index");

    mongoose.connect(config.database);

    //bodyParser to get our request/response parameters
    app.use(
      bodyParser.urlencoded({
        extended: false
      })
    );
    app.use(bodyParser.json({ limit: "50mb" }));

    //log request to console
    app.use(morgan("dev"));
    app.use(passport.initialize());

    //pass passport for connfiguration
    require("./config/passport")(passport);

    //allow cors
    app.use(function(req, res, next) {
      res.setHeader("Access-Control-Allow-Origin", "*");
      res.setHeader(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization"
      );
      res.setHeader(
        "Access-Control-Allow-Methods",
        "GET, POST, OPTIONS, PUT, PATCH, DELETE"
      );
      if (req.method === "OPTIONS") {
        console.log("!OPTIONS");
        res.end();
      }
      next();
    });

    routes(app);

    app.listen(port);
    console.log("express app started on port " + port);

路由/ index.js

const productApiRouter = require("./product.routes");
const userApiRouter = require("./user.routes");

module.exports = (app) => {
  app.use("/api", userApiRouter); //routes for users
  app.use("/products", productApiRouter); // routes for products
};

路由/ user.routes

require('../models/user')
const express = require('express');
const passport = require('passport')

const isAuthenticated = require('../controllers/auth.controller')

const router = express.Router();

var userController = require('../controllers/user.controller');


router.get('/', userController.getUser)
router.get('/cart', passport.authenticate('jwt', {
    session: false,
    failWithError: true
  }),  userController.getCart)
router.post('/deletecart/:id', userController.deleteCartById)
router.post('/authenticate', userController.authenticate)
router.post('/signup', userController.signupUser)
router.get('/verify_email', userController.verifyEmailByUrl)
router.post('/addcart/:id', userController.addItemToCart)
router.post('/update_user', userController.updateUser)

module.exports = router;

控制器/ user.controller.js 获取购物车方法

exports.getCart = (req, res) => {
  var token = getToken(req.headers);
  if (token) {
    var decoded = jwt.decode(token, config.secret);
    User.findOne(
      {
        email: decoded.email
      },
      function(err, user) {
        if (err) throw err;

        if (!user) {
          return res.status(404).send({
            success: false,
            message: "Not user found"
          });
        } else {
          var cart = user.itemsInCart;
          console.log(cart);
          var items = addItemCount.addItemCount(cart);
          console.log(items);
          res.status(200).send(JSON.stringify(items));
        }
      }
    );
  } else {
    console.log('Request ')
     res.status(403).send({
      success: false,
      message: "Unauthorized request"
    });
  }
};

config / passport --->护照配置

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../app/models/user');
const config = require('./database');

//add a JWT strategy to our passport
module.exports = function(passport) {
    var opts = {};
    opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("jwt");
    opts.secretOrKey = config.secret;
    passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
        User.findOne({
            id: jwt_payload.id //try to find a user given jwt_payload.id
        }, function(err, user) {
            if (err) {
                return done(err, false);
            }
            if (user) {
                done(null, user);
            } else {
                done(null, false)
            }
        });
    }));
}

getToken函数

 var getToken = function(headers) {
     if (headers && headers.authorization) {
         var parted = headers.authorization.split(' ');
         if (parted.length === 2) {
             return parted[1];
         } else {
             return null;
         }
     } else {
         return null;
     }
 };

 module.exports = getToken

1 个答案:

答案 0 :(得分:1)

在遇到问题后,我发现服务器无法使用授权令牌处理请求的原因。

对于NodeJS服务器,http请求的标头最大大小为80KB。参考:http_parser.h nodejs source code

#define HTTP_MAX_HEADER_SIZE (80*1024)

在问题中提到的请求中,我将一些Base64编码图像附加到JWT令牌,使其比NodeJS服务器允许的http请求更大。

因此解决方案是确保http请求的标头大小低于80K阈值。