我今天一直在修改passport-jwt,试图弄清楚如何在我的应用程序中正确设置它。我没有注册用户和保存jwt令牌的问题,但我不认为我使用护照这样做。现在我尝试登录用户,我总是收到错误Error: Failed to serialize user into session
。我在下面的一些文章中看到过:
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
但我似乎无法找到任何示例,甚至是护照文档的配置部分,它们解释了在哪里使用这些。它可能是我的问题的根源,但我不确定。我发现令人困惑的Passport的一个方面是JWT提取器。为什么我需要其中任何一个(即使它们是必需的)如果我想要做的就是将我的护照变成jwt令牌并将其保存在我的mongo数据库中?自己使用jsonwebtoken
并根据需要对字符串进行散列/取消散列并使用cookie-parser
创建自己的会话而不是使用像Passport这样的东西会不会更容易?我还尝试在休息电话中使用passport.authenicate(),但那些返回401。您可以在登录呼叫下面看到失败的尝试被注释掉。
请帮助,我觉得我是唯一一个发现护照比不那么健壮的东西更复杂的人,但我真的很乐意将其整理出来!
import express from 'express';
import path from 'path';
import bodyParser from 'body-parser';
import connection from './database';
import jwt from 'jsonwebtoken';
import cors from 'cors';
import crypto from 'crypto';
import passport from "passport";
import passportJWT from "passport-jwt";
const JwtStrategy = passportJWT.Strategy;
const ExtractJwt = passportJWT.ExtractJwt;
import { User } from './schema';
import { read } from 'fs';
const app = express();
const corsOptions = {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.use(cors(corsOptions));
app.use(passport.initialize());
app.use(passport.session());
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromBodyField('Password'),
secretOrKey: 'secretKey',
jsonWebTokenOptions: { expiresIn: 172800 }
}
passport.use(new JwtStrategy(jwtOptions, (jwt_payload, done) => {
User.findOne({ password: jwt_payload.sub }, (err, user) => {
user ? done(null, user) : done(null, false);
});
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.post('/test', (req, res) => {
console.log('Success');
console.log(req.body);
res.json(req.body);
});
app.post('/register', async (req, res) => {
if (req.body.FirstName
&& req.body.LastName
&& req.body.Email
&& req.body.Password
) {
const token = await jwt.sign(
{ Password: req.body.Password },
jwtOptions.secretOrKey,
{ expiresIn: '48h' }
);
const CreatedAt = await Date.now();
const newUser = await new User({
FirstName: req.body.FirstName,
LastName: req.body.LastName,
Email: req.body.Email,
Password: token,
});
await newUser.save(err => {
err ? console.log(err) : res.json(newUser);
});
}
throw new('error');
});
// app.post('/login', passport.authenticate('jwt', { session: false }),
// (req, res) => {
// console.log(req.user)
// if (req.body.Email && req.body.Password) {
// User.findOne({ Email: req.body.Email }, (err, user) => {
// if (err) return console.log(err);
// console.log(user);
// return user;
// }).then((res) => {
// jwt.verify(res.Password, jwtOptions.secretOrKey, (err, decoded) => {
// err ? console.log(err) :
// req.login(decoded, (err) => {
// // if (err) { return next(err); };
// if (err) {
// console.log(err)
// } else {
// console.log(decoded)
// }
// });
// });
// }).catch(err => console.log('Failed ', err));
// } else {
// console.log(req.body);
// }
// });
app.post('/login', (req, res) => {
if (req.body.Email && req.body.Password) {
User.findOne({ Email: req.body.Email }, (err, user) => {
if (err) return console.log(err);
console.log(user);
return user;
}).then((res) => {
// res.password returns the jwt string successfully
jwt.verify(res.Password, jwtOptions.secretOrKey, (err, decoded) => {
err ? console.log(err) :
req.login(decoded, (err) => {
// if (err) { return next(err); };
if (err) {
console.log(err) // always returns the error posted above
} else {
console.log(decoded)
}
});
});
}).catch(err => console.log('Failed ', err));
} else {
console.log(req.body);
}
});
app.listen(9000, () => {
console.log(`Listening on port 9000`);
});
自定义提取器尝试
const customExtractor = req => {
User.findOne({ Email: req.body.Email }, '_id', (err, user) => {
const token = jwt.sign(
{ id: user },
'secretKey',
{ expiresIn: '48h' }
);
return token;
});
基于@OrthoHomeDefense的帖子,我创建了以下内容并成功向客户端发送了一个jwt令牌:
app.post("/login", (req, res) => {
if (req.body.Email && req.body.Password) {
User.findOne({ Email: req.body.Email }, (err, user) => {
if(user.Password === req.body.Password) {
console.log()
var token = jwt.sign(JSON.stringify(user), jwtOptions.secretOrKey);
res.json({token: token});
} else {
console.log(err);
res.status(401).json({message:"Passwords did not match."});
}
});
} else {
res.status(401).json({message:"Please provide an email and a password."});
}
});
答案 0 :(得分:1)
首先,@ OrthoHomeDefense解决了我关于设置登录的初始问题,因为我对初始设置和使用护照需要遵循的内容感到困惑。
以下是我从客户端到服务器的电话。
export const test = token => {
console.log(token)
return dispatch => {
axios.post('http://localhost:9000/test',
{
headers: {'authorization': token},
data: {test: 'test', Token: token}
}
).then((res) => {
console.log(res.data);
})
.catch((error) => { console.log(error); });
}
}
接下来是我在服务器端进行的相关测试。
const customExtractor = req => {
let token = req.body.headers.authorization;
console.log(token);
return token;
}
const jwtOptions = {
jwtFromRequest: customExtractor,
secretOrKey: 'secretKey',
}
passport.use(new JwtStrategy(jwtOptions, (jwt_payload, done) => {
console.log('Success', jwt_payload);
User.findOne({id: jwt_payload.sub}, (err, user) => {
if (err) return done(err, false);
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
}));
我尝试了下面的提取器,每次只收到404,所以我创建了上面非常简单的提取器。如果您将令牌保存在cookie或类似的东西中,请按照您自己的提取器中的适用情况进行编辑,因为我发现自己更容易完成。
jwtFromRequest: ExtractJwt.fromBodyField('Token'),
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
jwtFromRequest: ExtractJwt.fromHeader("authorization"),
答案 1 :(得分:0)
您正在呼叫jwt.verify(...)
即验证令牌。您不需要在登录时验证令牌吗?您需要在登录时创建一个。
逐步完成此项/login
并告诉我它是如何运行的。
app.post("/login", function(req, res) {
if(req.body.name && req.body.password){
var name = req.body.name;
var password = req.body.password;
}
// usually this would be a database call:
//find user by username and password
if( !user ){
res.status(401).json({message:"no such user found"});
}
if(verify user is correct) {
//token is created here
var token = jwt.sign(payload, jwtOptions.secretOrKey);
//here is the response
res.json({message: "ok", token: token});
} else {
error
res.status(401).json({message:"passwords did not match"});
}
});