Nextjs 和 Passport 身份验证:无法将用户从会话中反序列化
Nextjs and Passport authentication: Failed to deserialize user out of session
尝试了几天后,我需要一些帮助。
我正在使用护照在我的 nextjs 应用程序中设置身份验证。登录后,会话存储在我的数据库中,用户对象位于 req 对象上。
问题是在浏览器或服务器重新启动后,使用 auth.js 中间件时 returns 错误消息“无法反序列化用户退出会话”。
用户登录端点
// pages/api/auth/login.js
import nextConnect from 'next-connect'
import '../../../lib/passport-local'
import passport from 'passport'
import auth from '../../../middleware/auth'
const jwt = require('jsonwebtoken');
require('dotenv').config();
const handler = nextConnect()
handler.use(auth).post(
(req, res) => {
passport.authenticate(
'local',
(err, user, {message}) => {
try {
if (err || !user) {
return res.json({ error: message });
}
req.login(
user,
(error) => {
if (error) return res.json({ error });
let { id, email, firstname, lastname } = user
return res.json({message: "Logged in",user: {id, email, firstname, lastname} });
}
);
// let { id, email, firstname, lastname } = user
// return res.json({message: "Logged in",user: {id, email, firstname, lastname} });
} catch (error) {
return res.json({error});
}
}
)(req, res);
}
护照攻略:
// lib/passport-local.js
import passport from 'passport'
const LocalStrategy = require('passport-local').Strategy
const Sequelize = require('sequelize');
const models = require('./../db/models/index');
require('dotenv').config();
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
let user = await models.User.findByMail(email) || false
if (!user) {
return done(null, false, {message: 'User not found'} );
}
const validate = await user.isValidPassword(password);
if (!validate) {
return done(null, false, {message: 'Wrong Password'} );
}
return done(null, user, {message: 'Logged in Successfully'} );
} catch (error) {
return done(error);
}
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try{
let user = await models.User.findByPk(id)
done(null, {id: user.id, firstname: user.firstname, lastname: user.lastname, email: user.email});
} catch (error) {
done(error);
}
});
授权中间件:
// middelware/auth.js
import nextConnect from 'next-connect'
import passport from 'passport'
import db from './../db/models/index'
var session = require('express-session');
var SequelizeStore = require("connect-session-sequelize")(session.Store);
var myStore = new SequelizeStore({
db: db.sequelize,
checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds.
expiration: 24 * 60 * 60 * 1000 // The maximum age (in milliseconds) of a valid session.
})
const auth = nextConnect()
.use(
session({
name: 'as-auth',
saveUninitialized:true,
secret: process.env.TOKEN_SECRET,
store: myStore,
resave: false,
cookie: {
maxAge: 60 * 60 * 1000, // 1000 hours,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
sameSite: 'lax',
},
})
)
.use(passport.initialize())
.use(passport.session())
myStore.sync();
export default auth
检查用户是否登录的端点
// pages/api/auth/loggedin.js
import nextConnect from 'next-connect'
import auth from '../../../middleware/auth'
const handler = nextConnect()
handler
.use(auth)
.get((req, res) => {
res.json({ user: req.user })
})
export default handler
已修复:这是因为我忘记在middelware/auth.js中导入passport-local,所以我的中间件没有序列化和反序列化功能。
尝试了几天后,我需要一些帮助。
我正在使用护照在我的 nextjs 应用程序中设置身份验证。登录后,会话存储在我的数据库中,用户对象位于 req 对象上。 问题是在浏览器或服务器重新启动后,使用 auth.js 中间件时 returns 错误消息“无法反序列化用户退出会话”。
用户登录端点
// pages/api/auth/login.js
import nextConnect from 'next-connect'
import '../../../lib/passport-local'
import passport from 'passport'
import auth from '../../../middleware/auth'
const jwt = require('jsonwebtoken');
require('dotenv').config();
const handler = nextConnect()
handler.use(auth).post(
(req, res) => {
passport.authenticate(
'local',
(err, user, {message}) => {
try {
if (err || !user) {
return res.json({ error: message });
}
req.login(
user,
(error) => {
if (error) return res.json({ error });
let { id, email, firstname, lastname } = user
return res.json({message: "Logged in",user: {id, email, firstname, lastname} });
}
);
// let { id, email, firstname, lastname } = user
// return res.json({message: "Logged in",user: {id, email, firstname, lastname} });
} catch (error) {
return res.json({error});
}
}
)(req, res);
}
护照攻略:
// lib/passport-local.js
import passport from 'passport'
const LocalStrategy = require('passport-local').Strategy
const Sequelize = require('sequelize');
const models = require('./../db/models/index');
require('dotenv').config();
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
let user = await models.User.findByMail(email) || false
if (!user) {
return done(null, false, {message: 'User not found'} );
}
const validate = await user.isValidPassword(password);
if (!validate) {
return done(null, false, {message: 'Wrong Password'} );
}
return done(null, user, {message: 'Logged in Successfully'} );
} catch (error) {
return done(error);
}
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try{
let user = await models.User.findByPk(id)
done(null, {id: user.id, firstname: user.firstname, lastname: user.lastname, email: user.email});
} catch (error) {
done(error);
}
});
授权中间件:
// middelware/auth.js
import nextConnect from 'next-connect'
import passport from 'passport'
import db from './../db/models/index'
var session = require('express-session');
var SequelizeStore = require("connect-session-sequelize")(session.Store);
var myStore = new SequelizeStore({
db: db.sequelize,
checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds.
expiration: 24 * 60 * 60 * 1000 // The maximum age (in milliseconds) of a valid session.
})
const auth = nextConnect()
.use(
session({
name: 'as-auth',
saveUninitialized:true,
secret: process.env.TOKEN_SECRET,
store: myStore,
resave: false,
cookie: {
maxAge: 60 * 60 * 1000, // 1000 hours,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
sameSite: 'lax',
},
})
)
.use(passport.initialize())
.use(passport.session())
myStore.sync();
export default auth
检查用户是否登录的端点
// pages/api/auth/loggedin.js
import nextConnect from 'next-connect'
import auth from '../../../middleware/auth'
const handler = nextConnect()
handler
.use(auth)
.get((req, res) => {
res.json({ user: req.user })
})
export default handler
已修复:这是因为我忘记在middelware/auth.js中导入passport-local,所以我的中间件没有序列化和反序列化功能。