【问题标题】:Express router sending HTML headers instead of JSON using Passport.jsExpress 路由器使用 Passport.js 发送 HTML 标头而不是 JSON
【发布时间】:2020-04-12 18:38:47
【问题描述】:

我有一个 API router.post 发送了错误的标头,我需要将标头设置为 application/json; charset=utf-8 但是它们以 text/html; charset=utf-8 发送,所以我不断收到 400 error。如何确保它们以 JSON 格式正确发送,以便我可以处理 POST 和必要的错误?

路由器

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

router.post('/signup', (req, res, next) => {
    User.register(new User({
        username: req.body.username,
        email: req.body.email
    }),
    req.body.password, (err, user) => {
        if (err) {
            res.statusCode = 500;
            res.setHeader('Content-Type', 'application/json');
            res.json({
                err: err
            });
        } else {
            passport.authenticate('local')(req, res, () => {
                User.findOne({
                    username: req.body.username
                }, (err, person) => {
                    res.statusCode = 200;
                    res.setHeader('Content-Type', 'application/json');
                    res.json({
                        success: true,
                        status: 'Registration Successful!',
                    });
                });
            })
        }
    })
});

router.post('/login', passport.authenticate('local'), (req, res) => {
    User.findOne({
        username: req.body.username
    }, (err, person) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'application/json');
        res.json({
            success: true,
            status: 'You are successfully logged in!'
        });
    })
});

router.get('/logout', (req, res, next) => {
    if (req.session) {
        req.logout();
        req.session.destroy((err) => {
            if (err) {
                console.log(err);
            } else {
                res.clearCookie('session-id');
                res.json({
                    message: 'You are successfully logged out!'
                });
            }
        });
    } else {
        var err = new Error('You are not logged in!');
        err.status = 403;
        next(err);
    }
});

App.js

const express = require('express');
const path = require('path');
const bodyParser = require("body-parser");
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

const usersRouter = require('./routes/users');

const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// Middleware
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(passport.initialize());
app.use(session({
    name: '...',
    secret: '...',
    saveUninitialized: false,
    resave: false
}));
app.use(passport.initialize());
app.use(passport.session());

//Passport
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

app.use('/', indexRouter);
app.use('/users', usersRouter);

【问题讨论】:

  • 我认为您的想法肯定有其他问题,因为您的router.post('/login', ...) 路由肯定会将内容类型设置为application/json,而不是text/html。你能描述一下这条路线是如何被使用的,以及你是如何得出它是text/html的结论吗?仅供参考,400 错误不是您的 router.post('/login', ...) 路由能够发送的,所以如果您真的收到 400 错误,那么它来自其他地方。
  • 我建议你在你的路由中设置一个断点并跟踪它,或者在路由中放置几个​​console.log() 语句并跟踪正在发生的事情。我的猜测是路由甚至没有被命中,错误来自服务器的其他地方。
  • router.post('/login', ...) 属于哪个路由器?我想看看您如何在app.js 文件中注册该路由器,并且我想知道您用于访问它的客户端的确切网址。
  • 您是否检查过您的路线中的代码是否真的受到攻击?我不认为它是。根据我在您的代码中看到的内容,我猜您的中间件 passport.authenticate('local', { failWithError: true }) 未能通过请求,并且可能是因为它没有在传入请求中找到预期的内容(根据 400 状态猜测)。我自己不知道护照,但这是下一个要看的地方。
  • 这个here 看起来像您的passport.authenticate('local', ...) 的预期用法。在您的路线中查找用户似乎也不正确。你要么已经在护照上这样做了,要么你不应该以这种方式使用护照。

标签: javascript node.js express passport.js


【解决方案1】:

我有一个发送错误标头的 API router.post,我需要将标头设置为 application/json; charset=utf-8 但是它们以 text/html 的形式发送; charset=utf-8 所以我不断收到 400 错误。如何确保它们以 JSON 格式正确发送,以便我可以处理 POST 和必要的错误?

400 错误显然来自护照中间件:

passport.authenticate('local', { failWithError: true })

在您的路线定义中:

router.post('/login', passport.authenticate('local'), (req, res) => {

您需要检查本地策略的代码。根据定义,passport.authenticate('local') 期待一种非常特定类型的传入数据。如果它没有找到该数据,它将断定这是一个错误的请求。

如果req.body.username 为空,则返回的错误为 Bad Request 400

您可以在通行证中间件之前添加自己的中间件以进行健全性检查req.body.username 并返回所需的错误,或者您可以自定义本地策略以返回所需的错误。


在我看来,您在护照本地策略中查找数据库中的用户,然后在您的路线中,您又在查找它,这似乎也很奇怪。你不应该这样做。您应该配置和使用护照来进行身份验证、使请求失败或将错误传递给您自己的错误处理代码。您不必通过再次查找用户来验证护照是否完成了它的工作。

【讨论】:

    猜你喜欢
    • 2012-04-03
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2014-05-27
    • 2014-09-20
    相关资源
    最近更新 更多