0

我有一个基本的 MERN 登录/注册应用程序,其中包含一个虚拟保护路由,仅对登录用户可见。我已经设置了与登录和注册相关的所有内容。我在 cookie 中从服务器发送 jwt 令牌。解决这个问题的方法很好。我可以注册,我可以登录。/protected但是当我对路由进行 GET 调用时,passport.jwt似乎不起作用。里面什么也没有发生。这是我的passport.js配置:

import {Strategy} from 'passport-jwt';
// import {ExtractJwt} from 'passport-jwt';
import passport from 'passport';
import mongoose from 'mongoose';
import {UserSchema} from '../models/userModel';
import {config} from './config';

const User = mongoose.model('User', UserSchema);

const cookieExtractor = (req) => {
    let token = null;
    if(req && req.cookies) {
        token = req.cookies['jwt'];
    }
    return token;
}

export const passportConfig = (passport) => {
    const opts = {};
    opts.jwtFromRequest = cookieExtractor;
    opts.secretOrKey = config.key;
    passport.use(
        new Strategy(opts, (jwt_payload, done) => {
            User.findById(jwt_payload.id)
                .then((user) => {
                    if(user) {
                        return done(null, user);
                    }
                    return done(null, false);
                })
                .catch((err) => {
                    console.log('Error in finding user by id in jwt.');
                });
        })
    );
};

这是userRoutes.js

import { addNewUser, loginUser, verifyLogin } from '../controllers/userController';

export const routes = (app) => {
    app.route('/users/register')
        .post(addNewUser);
    app.route('/users/login')
        .post(loginUser);
    app.route('/users/protected')
        .get(verifyLogin);
}

最后,这是我的verifyLoginloginUser控制器userController.js

export const loginUser = (req, res) => {
    console.log(req.body);
    if(mongoSanitize.has(req.body)) {
        return res.send(400).json({error: "Characters $ and . are prohibited. Use different values."});
    }

    const {errors, isValid} = validateLoginInput(req.body);
    if(!isValid) {
        return res.status(400).json(errors);
    }

    const userName = req.body.userName;
    const password = req.body.password;

    User.findOne({userName: userName})
        .then((user) => {
            if(!user) {
                return res.status(404).json({userNotFound: "Username not found."});
            }
            else {
                bcrypt.compare(password, user.password)
                    .then((isMatch) => {
                        if(isMatch) {
                            const payload = {
                                id: user.id,
                                name: user.fullName
                            };
                            const token = jwt.sign(payload, config.key, {expiresIn: 60});
                            res.cookie('jwt', token, {httpOnly: true, secure: false});
                            res.status(200).json({success: true, token: token});
                        }
                        else {
                            return res.status(400).json({incorrectPassword: "Password incorrect."});
                        }
                    })
            }
        });
};

export const verifyLogin = () => {
    console.log('protected'); //'protected' is printed
    passport.authenticate('jwt', {session: false}),
    (req, res) => {
        console.log('here'); //'here' is not printed
        const { user } = req;
        res.send(200).send({user});
    };
};

控制器loginUser工作得很好,我可以看到响应的令牌,而且我有一个带有 jwt key:value 对的 cookie。但是第三个控制器在调用verifyLogin后没有做任何事情。passport.authenticate

有什么想法我可能做错了什么吗?

4

2 回答 2

0

好的,所以我能够修复。其他有同样问题的人,问题是我没有将passport.authenticate其用作中间件,而是将它作为一个函数调用,并在成功验证时带有回调。这是我所做的更改:

userRoutes.js

export const routes = (app) => {
    app.route('/register')
        .post(addNewUser);
    app.route('/login')
        .post(loginUser);
    app.route('/protected')
        .get(passport.authenticate('jwt', {session:false}), verifyLogin);
}

然后verifyLogin将登录的用户信息发回:

export const verifyLogin = (req, res) => {
    console.log('here');
    const { user } = req;
    res.status(200).json({message:'Secure route', user: user});
};

其他一切都差不多。

于 2020-12-16T19:35:57.697 回答
0

在将时间更改为 1 小时之前,我遇到了同样的问题。看起来你写的值是以毫秒为单位的,所以60你应该写60000.

于 2022-01-03T22:28:01.287 回答