Express + PassportJS无法读取Flash消息

问题描述 投票:2回答:2

我有我的Express + Passport + Firebase项目,我在其中使用本地策略处理身份验证。由于我发现Passport将负责身份验证过程,因此我也发现它会接受Flash消息作为done()函数的第三个参数(在策略中)。但我不确定如何阅读它们:

我想我设置和读取Flash消息的流程是:

  1. 使用NPM安装connect-flash

  2. 导入后设置Express中间件:

import * as flash from 'connect-flash';
...
const app = express();
...
app.use(flash());
  1. 根据documentation在Express路由中配置护照认证:
// POST - /api/v1/admin/oauth/login
router.post(
    '/login',
    async (req: Request, res: Response) => { /* middleware function to validate input */ },
    passport.authenticate('local', {
        failureRedirect: '/api/v1/admin/oauth/login',
        failureFlash: true
    }),
    async (req: Request, res: Response) => { /* function after success login */
);
  1. 根据done(),将Flash消息包括在Passport configuration documentation方法中。
import { Strategy as LocalStrategy } from 'passport-local';
import db from '../../config/database';
import * as bcrypt from 'bcryptjs';

export default new LocalStrategy({ usernameField: 'email' }, async (email, password, done) => {
    const ref = db.collection('users').doc(email);
    try {
        const doc = await ref.get();
        if (!doc.exists) {
            return done(null, false, { error: 'Wrong email' });
        }

        const user = doc.data();

        const match: boolean = await bcrypt.compare(password, user.password);
        if (!match) {
            return done(null, false, { error: 'Wrong password' });
        }

        user.id = doc.id;
        delete user.password;

        return done(null, user);

    } catch(error) {
        return done(error);
    }
});
  1. 使用req.flash('error')阅读即显信息:
// GET - /api/v1/admin/oauth/login
router.get('/login', (req: any, res: Response) => {
    const result: IResult = {
        message: '',
        data: null,
        ok: false
    };
    if (req.flash('error')) {
        resultado.message = req.flash('error');
        console.log(req.flash('error'));
    }
    return res.status(400).json(result);
});

我以为从理论上讲,直到第5步为止,req.flash('error')中都有一个空数组。我做错了吗?

node.js typescript express flash passport.js
2个回答
1
投票

您传递的Flash消息错误!

done()的第三个参数应该是具有字段typemessage的对象:

return done(null, false, { message: 'Wrong email' });

类型默认为error

此API似乎没有明确记录,但在Passport.js文档的Configure章节的3rd example of the Verify Callback section中显示。

我创建了a repo,并提供了一个可复制性最低的工作示例。


0
投票

我一直在搜索,发现了一个解决方案,但在第二次登录尝试中仍然有效。

我修改问题的步骤使其生效:

  1. 使用NPM安装connect-flash

  2. 导入后设置Express中间件:

import * as flash from 'connect-flash';
...
const app = express();
...
app.use(flash());
  1. 根据documentation在Express路由中配置护照认证:
// POST - /api/v1/admin/oauth/login
router.post(
    '/login',
    async (req: Request, res: Response) => { /* middleware function to validate input */ },
    passport.authenticate('local', { 
        failureFlash: true,
        failureRedirect: '/api/v1/admin/oauth/login' 
    }),
    async (req: Request, res: Response) => { /* function after success login */
);
  1. 由于使用@Codebling,因此创建了另一条路线,以便可以显示即时消息:
// GET - /api/v1/admin/oauth/login
router.get('/login', (req: Request, res: Response) => {
    const result: IResult = {
        message: 'Auth ok',
        data: null,
        ok: true
    };

    let status: number = 200;
    const flashMessage: any = req.flash('error');

    if (flashMessage.length) {
        resultado.message = flashMessage[0];
        resultado.ok = false;
        status = 400; 
    }

    return res.status(status).json(result);
});
  1. 根据done(),将Flash消息包括在Passport configuration documentation方法中。
import { Strategy as LocalStrategy } from 'passport-local';
import db from '../../config/database';
import * as bcrypt from 'bcryptjs';

export default new LocalStrategy({ usernameField: 'email' }, async (email, password, done) => {
    const ref = db.collection('users').doc(email);
    try {
        const doc = await ref.get();
        if (!doc.exists) {
            return done(null, false, { message: 'Wrong email' });
        }

        const user = doc.data();

        const match: boolean = await bcrypt.compare(password, user.password);
        if (!match) {
            return done(null, false, { message: 'Wrong password' });
        }

        user.id = doc.id;
        delete user.password;

        return done(null, user);

    } catch(error) {
        return done(error);
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.