我是一名Node初学者,他正在尝试通过一些教程和示例来启动和运行。我想构建一个允许本地,Facebook,Twitter和谷歌登录的JSON API,所以我使用passport.js。目前我正在尝试将https://github.com/vitaly-t/pg-promise-demo与http://blog.slatepeak.com/refactoring-a-basic-authenticated-api-with-node-express-and-mongo/合并(对不起代码是如此不匹配的样式)并且遇到了我的登录POST返回的问题:无法发布/ auth / login /本地,当我提供正确的凭据时,如果我的凭据不好,它可以正常工作我真的不明白为什么行为会有所不同,除非本地护照在我没有考虑的后台做某事。我认为相关的文件是:
SERVER.js
'use strict';
var db = require('./db/db.js').db
, express = require('express')
, auth = require('./routes/auth')
, router = express.Router()
, app = express()
, routes = require('./routes/routes.js')
, bodyParser = require('body-parser') //must be before passport
, config = require('./conf/main');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/auth', auth);
// Enable CORS from client-side - Will I need this?
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Access-Control-Allow-Credentials");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
//////////////////////////////////////////////
// Users Web API
//////////////////////////////////////////////
app.post('/users/local', routes.userAddLocal);
app.get('/users', routes.getAllUsers); //This should go into the Admin App. Will they both be able to use Postgres at once?
app.listen(config.port, () => {
console.log('\nReady for requests on http://localhost:' + config.port);
});
AUTH.js
'use strict';
///////////////////////// Passport Setup
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, JwtStrategy = require('passport-jwt').Strategy
, ExtractJwt = require('passport-jwt').ExtractJwt
, jwt = require('jsonwebtoken')
, db = require('../db/db.js').db
, config = require('../conf/main')
, express = require('express')
, bodyParser = require('body-parser') //must be before passport
, bcrypt = require('bcrypt-nodejs');
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling Passport where to find the secret
secretOrKey: config.secret
};
passport.use('local', new LocalStrategy({
usernameField: 'email'
, passReqToCallback: false
, session: false //Turn off sessions, this is a stateless REST service using JWT
},
function(username, password, done) {
db.users.findByEmail(username)
.then(function (user){
if (!user) { return done(null, false); }
var pwMatch = bcrypt.compareSync(password, user.password);
if (!pwMatch) { return done(null, false); }
return done(null, user);
})
.catch(function(error){
return done(error);
})
}
));
passport.use('jwt', new JwtStrategy(jwtOptions, function(payload, done) {
console.log("jwt strategy top line");
db.users.findById(payload._id) //maybe need payload.doc._id or payload.document._id
.then(function (user){
if (user) {
done(null, user);
} else {
done(null, false);
}
})
.catch(function(error){
return done(err, false);
})
}));
function generateToken(user) {
return jwt.sign(user, config.secret, {
expiresIn: 10080 // in seconds
});
};
var authRoutes = express.Router();
authRoutes.use(bodyParser.urlencoded({ extended: true }));
authRoutes.use(bodyParser.json());
authRoutes.use(passport.initialize());
authRoutes.post('/login/local', passport.authenticate('local', {
function(req, res) {
var tokenObj = auth.generateToken({email: req.body.email, displayName: req.body.DisplayName});
res.status(201).json({
token: 'JWT ' + tokenObj,
user: req.body.displayName
});
},
failureRedirect: '/auth/notauth',
session: false
}));
authRoutes.get('/notauth', function (req, res){
res.status(401).send("Login Failed");
});
module.exports = authRoutes;
module.exports.generateToken = generateToken;
任何人都可以提供的帮助将非常感激。
编辑#1:我尝试重写PORT的路由('login / local'),现在它登录但由于某种原因我没有req和req.user对象可供我使用。我google的所有内容都说我需要包含会话,但我没有使用会话,所以这对我来说不合适。这是新路线:
authRoutes.post('/login/local', passport.authenticate('local',
function(req, res){
console.log("authentication successful");
var tokenObj = generateToken({email: req.body.email, displayName: req.body.DisplayName});
res.status(201).json({
token: 'JWT ' + tokenObj,
user: req.body.displayName
});
}
, {failureRedirect: '/auth/notauth'}
, {session: false}
));
有人可以告诉我如何解决这个问题,以便根据Passport文档提供req.user吗?
编辑#2:似乎成功函数是一个null,一个对象包含来自users表的db记录。看起来就像我在用户成功登录时返回的内容。不知怎的,我已经破坏了Passport-Local而且它没有这样做。
答案 0 :(得分:1)
可以使用一些更改:
passport.use('local', new LocalStrategy({
usernameField: 'email'
// , passReqToCallback: false
, passReqToCallback: true
, session: false //Turn off sessions, this is a stateless REST service using JWT
},
//function(username, password, done) {
function(req, username, password, done) {
db.users.findByEmail(username)
.then(function (userRecord){
if (!userRecord) { return done(null, false); }
var pwMatch = bcrypt.compareSync(password, userRecord.password);
if (!pwMatch) { return done(null, false); }
//return done(null, userRecord);
return done(null, req, userRecord);
})
.catch(function(error){
return done(error);
})
}
));
和
authRoutes.post('/login/local', passport.authenticate('local',
function(err, req, userRecord){
console.log("authentication successful");
var tokenObj = generateToken({email: userRecord.email, displayName: userRecord.DisplayName});
var res = req.res; //nfi why i need this
res.status(201).json({
token: 'JWT ' + tokenObj,
user: userRecord.displayName
});
}
, {failureRedirect: '/auth/notauth'}
, {session: false}
));