我目前面临以下错误,我正在 Node js 中为虚拟商店开发一个 API。用户为了将其商品放入购物车,需要进行身份验证。身份验证是通过 JWT 处理的,我使用 Passport 模块来实现该建议。
对于需要身份验证的路由,当使用“Authentication” header 及其对应的“JWT ey...” token 使用 API 时,服务器不会处理任何请求。仅响应 OPTIONS 预检请求,仅此而已。 我尝试使用 httpClient 从角度前端使用/api/cart 和授权 header ,并在 chrome devTools 中收到以下错误
我也尝试过使用 postman ,发送授权 header ,但出现无法获得任何响应屏幕。
我正在记录 OPTIONS 请求 header 。以下是使用授权 header 点击/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 - -
服务器.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;
Controller /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 ---> 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
最佳答案
在解决这个问题之后,我找到了服务器无法处理带有授权 token 的请求的原因。
对于 NodeJS 服务器,http 请求的 header 最大大小为 80KB
。引用:http_parser.h nodejs source code
#define HTTP_MAX_HEADER_SIZE (80*1024)
在问题中提到的请求中,我将一些 Base64 编码的图像附加到 JWT token ,使其比 NodeJS 服务器允许的 http 请求 header 大小更大。
因此,解决方案是确保 http 请求的 header 大小低于 80K
阈值。
关于node.js - Node + Express 服务器在 OPTIONS 预检请求后未响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48876574/