#node.js #express #passport.js
#node.js #выражать #passport.js
Вопрос:
При вызове незащищенного маршрута я могу распечатать и ответить значениями в req.cookies
{
"cookies": {
"connect.sid": "s:PqWvDsoKLMeCyRd8pGN<removed>",
"testCookie": "testValue"
},
"signedCookies": {}
}
Однако этот маршрут возвращает 401 Unauthorized
router.get('/authCheck', passportWithLocalStrategy.authenticate('local'), (req: Request, res: Response, next: NextFunction) => {
res.status(204).send();
});
Кто-нибудь знает, что может быть причиной того, что файл cookie сеанса не аутентифицируется?
Вот мой основной файл server.ts, удаление / сериализация и стек промежуточного программного обеспечения:
// called to set a cookie initially
passport.serializeUser((user: any, callback) => {
callback(null, user.id as string);
});
// called every time a request is made
passport.deserializeUser(async (userId: string, callback) => {
const pgClient = new PgClient();
try {
pgClient.connect();
const userRecord = (await pgClient.query('SELECT * FROM app_user WHERE CAST(id as text) = CAST($1 as text)', [userId])).rows[0];
pgClient.end();
callback(null, userRecord);
} catch (error) {
callback(error);
}
});
server
.use(cors())
.use(express.json())
.use(expressSession({ secret: process.env.SESSION_SECRET! }))
.use(cookieParser())
.use(passport.initialize())
.use(passport.session())
.use(rootRouter)
<other routers removed>
Я настроил свою Passport LocalStrategy, как показано:
async function useDatabaseToVerifyUserAndPassword(localUserName: string,
localPassword: string, doneCallback: any) {
const pgClient = new PgClient();
try {
await pgClient.connect();
const queryResult = await pgClient.query(selectUserQuery, [localUserName]);
pgClient.end();
const userData: UserMatch = queryResult.rows[0];
if (typeof userData === 'undefined' || typeof userData.password_hash === 'undefined') {
return doneCallback(null, false);
}
const hashesMatch: boolean = await bcrypt.compare(localPassword, userData.password_hash);
if (hashesMatch) {
return doneCallback(null, userData);
}
return doneCallback(null, false); // username not found or passHash mismatch. Prints 401 UnAuth
} catch (error) {
return doneCallback(error, false);
}
}
const strategyOptions = {
usernameField: 'localUserName',
passwordField: 'localPassword',
};
const localStrategy = new LocalStrategy(strategyOptions, useDatabaseToVerifyUserAndPassword);
passport.use(localStrategy);
export default passport;
Вышеуказанный экспорт переносится в файл маршрутизатора (для маршрута в /authCheck
) как passportWithLocalStrategy
. Если я просто импортирую passport
из папки библиотеки в этот файл, маршрут прерывается, зависая на неопределенный срок.
Обновить
Я попытался снять защиту с маршрута и получить доступ req.isAuthenticated()
. Он всегда возвращает false, даже если существует файл cookie сеанса.
Я вижу эту информацию, напечатанную при входе в систему req.session
Session Session {
cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }
Комментарии:
1. Я бы проверил, что у
localUserName
иlocalPassword
есть значения. Если вы запрашиваете маршрут без указания имени пользователя и пароля в теле запроса, passport автоматически вернет401
. Если это сработает, я бы проверил, что пользователь возвращается в вашем запросе к базе данных и чтоdone(null, false)
не вызывается.2. @jasonandmonte да, это работает, когда я предоставляю
localUsername
иlocalPassword
. Нет ли способа полагаться на файл cookie сеанса сам по себе? Я думал, что смысл сеансов в том, чтобы избежать необходимости указывать имя пользователя и пароль при каждом запросе.
Ответ №1:
У вас должен быть отдельный маршрут входа, который вызывает, passport.authenticate
после того, как он успешно вернется, passport добавит req.session.passport
значение с сериализованным идентификатором пользователя. Вам нужно выполнить этот процесс только один раз при входе пользователя в систему.
/authCheck
Затем маршрут может быть реорганизован с помощью промежуточного программного обеспечения, которое просто проверяет, что пользователь все еще вошел в систему.
router.get('/authCheck', (req: Request, res: Response, next: NextFunction) => {
// passport isAuthenticated method
if(req.isAuthenticated()){
//req.isAuthenticated() will return true if user is logged in
return res.status(204).send();
} else{
res.redirect("/login");
}
});
Комментарии:
1. Спасибо, я замечаю, что запросы от postman и браузера Chrome
req.isAuthenticated()
установлены наfalse
, хотя в обоих файлах cookie сеанса присутствуют. Есть идеи, что может быть причиной этого?2. Интересно.
req.session.passport
Присутствует в сеансе после входа в систему?