Passport js中的isAuthenticated()始终返回false

时间:2019-03-16 17:53:57

标签: javascript node.js passport.js

我一直在浏览论坛,但是我无法在代码中找到错误,它始终会导致错误,并且无法解决,请帮助我... 有没有其他方法可以验证用户身份而不是护照,以便我可以使用它。我要添加更多句子,因为它不允许我发布查询,对不起。

const http = require("http"),
  hostname = "127.0.0.1",
  port = 3000,
  bodyParser = require("body-parser"),
  mongoose = require("mongoose"),
  express = require("express"),
  passport = require("passport"),
  localStrategy = require("passport-local"),
  passportLocalMongoose = require("passport-local-mongoose"),
  User = require("./models/user");
app = express();
mongoose.connect("mongodb://localhost/drive", { useNewUrlParser: true });
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(passport.initialize());
app.use(passport.session());
app.use(
  require("express-session")({
    secret: "Beta tumse na ho payega",
    resave: false,
    saveUninitialized: false
  })
);
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(bodyParser.urlencoded({ extended: true }));
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
});
app.get("/", function(req, res) {
  res.render("index");
});
app.get("/register", function(req, res) {
  res.send("hello");
});
app.get("/login", function(req, res) {
  res.render("login");
});
app.post(
  "/login",
  passport.authenticate("local", {
    successRedirect: "/",
    failureRedirect: "/login"
  }),
  function(req, res) {}
);

app.get("/logout", function(req, res) {
  req.logout();
  res.redirect("/");
});

function isLoggedIn(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  } else {
    console.log("Not logged");
    res.redirect("/login");
  }
}
app.get("/secret", isLoggedIn, function(req, res) {
  res.send("You are logged in");
});
app.post("/register", function(req, res) {
  if (req.body.password === req.body.cpassword) {
    User.register(
      new User({ username: req.body.username }),
      req.body.password,
      function(err, user) {
        if (err) console.log(err);
        else
          passport.authenticate("local")(req, res, function() {
            res.send("signed up");
          });
      }
    );
  } else res.send("Password Mismatch");
});
//DRIVE SCHEMA
//var driveSchema = mongoose.Schema({
//  title: String,
//  created: { type: Date, default: Date.now }
//});
app.listen(port, hostname, function() {
  console.log("Server is running at " + hostname + "/" + port);
});

//./models/user.js  file

const mongoose = require("mongoose"),
  passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
  username: String,
  password: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);

2 个答案:

答案 0 :(得分:1)

我已经使用passportjwt库来验证和维护用户的会话。无需在服务器端维护用户会话。

apis / apis.js:此文件具有所有api端点。 /login网址将使用护照对用户进行身份验证,并使用jwt将令牌发送给客户端

const passport = require('passport')
const expRoute = require('express').Router();
let exporter = process.exporter;
expRoute.post('/login', (req, res, next) => {
  passport.authenticate(
    'local', 
    { 
        // successRedirect: '/',
        // failureRedirect: '/login',
        successFlash: 'Welcome!',
        failureFlash: 'Invalid username or password.' 
    },
    (err, user, info) => {
        if (err) {
            return res.status(500).json(err)
        }
        else if (user) {
            return res.status(200).json({
                token: exporter.generateToken(user)
            })
        }
        else {
            return res.status(400).json(info)
        }
    }
  )(req, res, next);
})
expRoute.get('/view', exporter.authenticateToken, (req, res) => {
    let param = req.finalTokenExtractedData
    if (param && exporter.isObjectValid(param, 'tokenId', true, true)) {
        let condition = {
            _id: param.tokenId
        }
        let options = {
            _id: 0,
            password: 0,
            __v: 0
        }
        process.USER.findOne(condition, options) // mongo find
        .then((data) => {
            res.status(200).json({
                 result: data,
                 msg: 'success'
            })
        })
       .catch((mongoErr) => {
            exporter.logNow(`USER mongo Error: ${mongoErr}`)
            res.status(400).json({
                msg: 'user not found'
            })
        })
    }
    else {
        res.status(404).json({
            msg: 'invalid token'
        })
    }
})
module.exports = expRoute

common / env.js:此文件将初始化所有连接,例如mongo,需要将少数文件用作全局文件

process.CONFIG = require('../configs/config.json')

process.exporter = require("../lib/exporter.js")

process.dbInit = (globalName, mongoUrl, collectionName) => {
    require("../models/db-init.js")(mongoUrl, collectionName)
    .then((modelObj) => {
        process[globalName] = modelObj // will be used as global
    })
    .catch((dbInitErr) => {
        process.exporter.logNow(`dbInit Error: ${dbInitErr}`)
        process.exit()
    });
}

lib / exporter.js:此文件具有包含所有主要功能(如mongo连接,authenticateToken,verifyPassword等)的导出程序类。

const fs = require('fs'),
    redis = require("redis"),
    path = require("path"),
    mongoose = require('mongoose'); mongoose.set('useCreateIndex', true);
const Schema = mongoose.Schema;
var bcrypt = require('bcryptjs')
var jwt = require('jsonwebtoken')

class Exporter  {
    mongoConnection(mongoURI, schemaObj) {
        return new Promise(async (resolve, reject) => {
            if (!mongoURI || typeof mongoURI == 'undefined' || mongoURI.length < 1)
                return reject('invalid mongo connection url');
            return resolve(mongoose.createConnection(mongoURI, { useNewUrlParser: true }))
        })
    }
    createMongoSchema(schemaObj) {
        return (new Schema(schemaObj));
    }
    createMongoModel(mongoDB, collectionName, newSchema) {
        if (newSchema)
            return mongoDB.model(collectionName, newSchema)        
        return mongoDB.model(collectionName)
    }
    authenticateToken(req, res, next) {
        const bearerHeader = req.header('authorization')
        if (typeof bearerHeader != 'undefined') {
            const bearer = bearerHeader.split(' ')
            const bearerToken = bearer[1] 
            jwt.verify(bearerToken, process.CONFIG.jwt.token.activated, (err, data) => {
                if (err)
                    res.status(400).json({
                        msg: "Invalid token or please try to login again"
                    })
                else {
                    process.exporter.getSingleHashKeysValuesFromRedis('expired_token', bearerToken)
                    .then((redisTokendata) => {
                        if (redisTokendata)
                            res.status(400).json({
                                msg: "token expired"
                            })
                        else {
                            req.finalTokenExtractedData = data
                            // if (req.originalUrl.trim() == process.logoutURL.trim())
                                req.jwtToken = {
                                    token: bearerToken,
                                    secret: process.CONFIG.jwt.token.activated
                                }
                            next()
                        }
                    })
                    .catch((redisTokenError) => {
                        process.exporter.logNow(`redis token error: ${redisTokenError}`)
                        res.status(400).json({
                            msg: "Some went wrong while checking token. Please try later."
                        })
                    })
                }
            })
        }
        else 
            res.status(400).json({
                msg: "invalid token"
            })
    }
    generateToken(data) {
        let expiry = new Date();
        // expiry.setDate(expiry.getDate() + 7)
        expiry.setMinutes(expiry.getMinutes() + 5)
        return jwt.sign({
            tokenId: data._id,
            exp: parseInt(expiry.getTime() / 1000),
        }, process.CONFIG.jwt.token.activated)
    }    
    createPassword(password) {
        return new Promise((resolve, reject) => {
            if (typeof password == 'undefined' && password == '')
                return reject('password empty')
            bcrypt.hash(password, 10, async (bErr, hash) => {
                if (bErr)
                    reject(bErr)
                else
                    resolve(hash)
            })
        })
    }
    verifyPassword(enteredPassword, savePassword) {
        return bcrypt.compareSync(enteredPassword, savePassword)
    }
}
module.exports = (new Exporter());

index.js:这是您将执行node index.js的文件。

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const passport = require('passport');

require('./common/env')
require('./configs/passport')

const app = express()

const cors = require('cors')
app.use(cors());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(passport.initialize())

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

let apis = require('./apis/api')
app.use('/user', apis)

/**
 * 404 Handler
 */
app.use((req, res, next)=>{
    return res.status(404).send("Endpoint "+req.url +" not found");
})

/**
 * if any error or exception occurred then write into a JS file so that app can be restarted
 */
process.on('uncaughtException', (err) => {
    console.error(err.stack);
});


app.listen(3000, function(server) {
    console.log("App listening at 3000");
});

成功执行index.js文件并侦听端口3000后,使用此URL http://localhost:3000/user/login进行身份验证,它将接受您的用户名和密码,然后使用护照进行身份验证并将令牌发送给客户端作为回应。令牌可以包含加密形式的用户数据,并且具有到期时间。

参考链接:https://github.com/arjun-707/login-logout-jwt-nodejs

答案 1 :(得分:0)

您需要express-session模块。

server.js

// Require a possible config.js file with your configuration variables
const Config = require('./models/config.js');
// If the config module is formed as a class
const config = new Config();
const express = new('express');
const app = express();

const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const uuid = require('uuid/v4');
const mongoose = require('mongoose');
// Require your custom passport local strategy file
const passport = require('./models/sessions');

mongoose.connect('mongodb://localhost:27017/your_db_name', {
    useNewUrlParser: true
});

// Set the session options
app.use(session({
    // Use UUIDs for session IDs
    genid: (req) => {
        return uuid()
    },
    // If you want to store the session in MongoDB using mongoose
    // Require your personal mon
    store: new MongoStore({
        mongooseConnection: mongoose.connection
    }),
    // Define the session secret in env variable or in config file
    secret: process.env.SESSION_SECRET || config.sessionSecretKey,
    resave: false,
    saveUninitialized: true
}));
// Initialize the passport module
app.use(passport.initialize());
// Tell to passport to use session
app.use(passport.session());

./ models / session.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt-nodejs');
// Your custom MongoDB connection module
const db = require('./db');

// Configure passport.js to use the local strategy
passport.use(new LocalStrategy({
        usernameField: 'username'
    },
    (username, password, done) => {
        db.User.find({
            username: username // But it could use email as well
        }).then(res => {
            const user = JSON.parse(JSON.stringify(res[0]));
            if (!user) {
                return done(null, false, {
                    message: 'Invalid credentials.\n'
                });
            }
            if (!bcrypt.compareSync(password, user.password)) {
                return done(null, false, {
                    message: 'Invalid credentials.\n'
                });
            }
            return done(null, user);
        }).catch(error => done(error));
    }
));

// Tell passport how to serialize the user
passport.serializeUser((user, done) => {
    done(null, user._id);
});

// Tell passport how to deserialize the user
passport.deserializeUser((id, done) => {
    db.User.find({
        _id: id
    }).then(res => {
        const response = typeof res !== undefined && res.length != 0 ? JSON.parse(JSON.stringify(res[0])) : null;
        done(null, response)
    }).catch(error => done(error, false))
});

// Export passport for external usage
module.exports = passport;

./ models / db.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const uuid = require('uuid/v4');

// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/your_db_name', {
    useNewUrlParser: true
});

// Define the models container
let models = {};

// Prepare your user schema
const userSchema = Schema({
    username: {
      type: String,
      required: true
    },
    password: {
      type: String,
      required: true
    }
});

// Assign the user schema
models.User = mongoose.model('User', userSchema);

// Export for external usage
module.exports = models;

/*
In that way you can wrap in "models" all schemas:

const newSchema = Schema({
  name: String
});
models.Newschema = mongoose.model('Newschema', newSchema);

module.exports = models;

And use it externally like:

const db = require('./models/db');

db.User.find({}).then(docs => {}).catch(err => {});
db.Newschema.find({}).then(docs => {}).catch(err => {});

Etc....

*/

./ models / config.js

class Config {
  
  constructor() {
    this.sessionSecretKey = "my-awesome-secretkey";
    /* And other configurations */
  }

}

module.exports = Config;

/*

Externally use like:

const Config = require('./models/config');
const config = new Config();

let sessionSecretKey = config.sessionSecretKey;

*/

然后您可以在登录后使用req.isAuthenticated()

// POST the username and password to '/login' router
app.post('/login', (req, res, next) => {
    passport.authenticate('local', (err, user, info) => {
        if (info) {
            return res.send(info.message)
        }
        if (err) {
            return next(err);
        }
        if (!user) {
            return res.sendStatus(404); // Is a shortcut
            // OR -> res.status(404).end();
            // OR -> res.status(404).send('Not found'); as you like
        }
        req.login(user, (err) => {
            if (err) return next(err);
            // Store the user object retrieved from MongoDB in `req.session`
            req.session.user = user;
            return res.sendStatus(200); // Is a shortcut
            // OR -> res.status(200).end();
            // OR -> res.status(200).send('OK'); as you like
        })
    })(req, res, next);
});

// The logout logic
app.get('/logout', verifySession, function (req, res) {
    req.session.destroy(function (err) {
        req.logout();
        res.redirect('/');
    });
});

// Verify the session to protect private routers
function verifySession(req, res, next) {
    if (req.isAuthenticated()) {
        next();
    } else {
        // Forbidden
        res.redirect('/');
        // OR -> res.sendStatus(403);
        // OR -> res.status(403).end();
        // OR -> res.status(403).send('Forbidden'); as you like
    }
}

当然,您必须使用npm install文件中定义的所有必需依赖项来运行package.json,或者使用npm i express-session@latest --s手动安装所有必需的依赖项:npm i module-name@latest --s

别忘了

const server = app.listen(config.port || 3000, () => {
    console.log(`Server running on ${server.address().port} port.`);
});

server.js文件的末尾。希望对您有用。