【问题标题】:How to properly logout with JWT using Passport Strategies?如何使用 Passport Strategies 正确注销 JWT?
【发布时间】:2021-03-12 21:36:49
【问题描述】:

我是 JWT 和 Passport 的新手,所以我开始关注 NoobCoder 在 Youtube 上的 MERN 教程,该教程涉及使用 JWT 进行身份验证和授权。我到达了路由处理'/logout'的部分,我得到了邮递员的答复未经授权。到目前为止的代码看起来完全一样。有人可以帮我理解这里出了什么问题吗?

我已将代码附在底部。如果需要更多信息,请告诉我。

代码如下:

app.js

const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
app.use(cookieParser());
app.use(express.json());

mongoose.connect('mongodb://localhost:27017/mernauth', {useNewUrlParser: true, useUnifiedTopology: true}, () => {
   



console.log('Successfully connected to DB');
});

const userRouter = require('./routes/User');
app.use('/user', userRouter);

app.listen(5000, () => {
    console.log('express server started');
});

passport.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy;
const User = require('./models/User');

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

// Authorization
passport.use(new JwtStrategy({
    jwtFromRequest: cookieExtractor,
    secretOrKey: 'NoobCoder'
}, (payload, done) => {
    User.findById({_id: payload.sub}, (err, user) => {
        if(err) {
            return done(err, false);
        }
        if(user) {
            return done(null, user);
        }
        else {
            return done(null, false);
        }
    })
}));

// Authenticated local strategy using username and password
passport.use(new LocalStrategy((username, password, done) => {
    User.findOne({username}, (err, user) => {
        // Something went wrong with DB
        if(err) {
            return done(err);
        }

        // If no user exists; null = no error; false = user does not exist
        if(!user) {
            return done(null, false);
        }

        // Check if password is correct; callback cb = done
        user.comparePassword(password, done);
    });
}));

User.js(路由)

const express = require('express');
const userRouter = express.Router();
const passport = require('passport');
const passportConfig = require('../passport');
const JWT = require('jsonwebtoken');
const User = require('../models/User');
const Todo = require('../models/Todo');

const signToken = userID => {
    return JWT.sign({
        iss: "NoobCoder",
        sub: userID
    }, "NoobCoder", {expiresIn: "1h"});
}

userRouter.post('/register', (req, res) => {
    const {username, password, role} = req.body;
    User.findOne({username}, (err, user) => {
        if(err) {
            res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
        }
        if(user) {
            res.status(400).json({message: {msgBody: "Username is already taken", msgError: true}})
        }
        else {
            const newUser = new User({username, password, role});
            newUser.save(err => {
                if(err) {
                    res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
                }
                else {
                    res.status(201).json({message: {msgBody: "Account Successfully Created", msgError: false}})
                }
            })
        }
    })
});

userRouter.post('/login', passport.authenticate('local', {session: false}), (req, res) => {
    if(req.isAuthenticated()) {
        const {_id, username, role} = req.user;
        const token = signToken(_id);
        res.cookie('access_token', token, {httpOnly: true, sameSite: true});
        res.status(200).json({isAuthenticated: true, user: {username, role}})
    }
});

userRouter.get('/logout', passport.authenticate('jwt', {session: false}), (req, res) => {
    res.clearCookie('access_token');
    res.json({user: {username: '', role: ''}, success: true});
});

module.exports = userRouter;

User.js(模型)

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
        min: 6,
        max: 15
    },
    password: {
        type: String,
        required: true,
    },
    role: {
        type: String,
        enum: ['user', 'admin'],
        required: true
    },
    todos: [{type: mongoose.Schema.Types.ObjectId, ref: 'Todo'}]
});

UserSchema.pre('save', function(next) {
    if(!this.isModified('password')) {
        return next()
    }

    bcrypt.hash(this.password, 10, (err, passwordHash) => {
        if(err) {
            return next(err);
        }

        this.password = passwordHash;
        next();
    });
});

UserSchema.methods.comparePassword = function(password, cb) {
    bcrypt.compare(password, this.password, (err, isMatch) => {
        if(err) {
            return cb(err);
        }
        else {
            if(!isMatch) {
                return cb(null, isMatch)
            }
            return cb(null, this);
        }
    })
};

module.exports = mongoose.model('User', UserSchema);

【问题讨论】:

  • 你找到解决办法了吗?

标签: authentication jwt authorization passport-local passport-jwt


【解决方案1】:

/logout 路由可能是未经授权的,因为 JWT 令牌不存在?

可以通过确保 cookieExtractor 函数返回令牌来验证 JWT 令牌的存在

【讨论】:

    【解决方案2】:
    app.get('/logout', function(req, res){
      req.logout();
      res.redirect('/');
    });
    

    Source

    【讨论】:

    • 如果您不维护会话,则无法从 JWT 注销
    猜你喜欢
    • 2020-10-20
    • 2020-08-11
    • 2019-01-19
    • 2018-01-14
    • 1970-01-01
    • 2018-01-25
    • 2019-05-09
    • 2017-10-25
    • 2018-02-06
    相关资源
    最近更新 更多