#node.js #typescript #express #passport.js
Вопрос:
У меня есть система аутентификации на основе машинописного текста Nodejs, которая работает с использованием паспорта.
Моя проблема в том, что когда я использую req.user
маршрут, я получаю эту ошибку req.user
: Object is possibly 'undefined'.
Это нормальное поведение Typescript, но я использую промежуточное программное обеспечение для защиты маршрутов, которые я хочу req.user
в них использовать, и этот способ req.user
не может быть неопределенным.
Здесь я расширяю Express.User
тип:
import { users } from "@prisma/client";
declare global {
namespace Express {
interface User extends users {}
}
}
Это промежуточное программное обеспечение, которое я использую для защиты маршрутов для зарегистрированных пользователей:
export function checkIsAuthenticated(req: Request, res: Response, next: NextFunction) {
if (req.isAuthenticated()) {
if (!req.user) req.logOut();
else return next();
}
res.status(400).json({
errors: [{ message: "no user logged in" }],
});
}
И это маршрут для получения информации о пользователе:
export function userRoute(req: Request, res: Response) { // defining the route
res.json({
id: req.user.id, // I'm getting the error in these 4 lines
username: req.user.username, //
email: req.user.email, //
role: req.user.role, //
});
}
router.get("/user", checkIsAuthenticated, userRoute); // using the route
Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика. Вот почему промежуточное программное обеспечение предназначено для.
Я плохо разбираюсь в машинописи, поэтому мне нужна помощь, чтобы это исправить. Спасибо
Комментарии:
1. «Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика». Я бы не сказал, что это плохая практика. Это дало бы вам хорошую явную ошибку, если бы вы, например, пропустили промежуточное программное обеспечение аутентификации при создании одного из этих маршрутов.
Ответ №1:
Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика.
Мое первое решение, пытающееся удовлетворить это требование, не сработало, поэтому я удалил его. Я оставил свое второе решение, которое заключается в:
Но я бы сказал, что нет ничего плохого в том, чтобы проверить запрос пользователя и выдать себе приятное полезное сообщение об ошибке, если вы случайно использовали один из этих обработчиков на маршруте, на котором вы забыли установить аутентификацию. Это выглядело бы так:
type RequestWithUser = Request amp; {user: typeOfUserObject};
function assertHasUser(req: Request): asserts req is RequestWithUser {
if (!( "user" in req)) {
throw new Error("Request object without user found unexpectedly");
}
}
Затем ваш обработчик для этих маршрутов:
export function userRoute(req: Request, res: Response) {
assertHasUser(req);
// ...you can use `req.user` here...
});
(На самом деле вам не нужен явный RequestWithUser
тип, вы могли бы просто использовать asserts req is Request amp; {user: typeOfUserObject}
.)
Комментарии:
1. Большое вам спасибо за вашу помощь! Было бы здорово, если бы express мог обнаружить, что я проверяю свойство запроса в промежуточном программном обеспечении для запроса, но я думаю, что в настоящее время это ограничение JS или TS, и мы должны пока обойти его.
Ответ №2:
export function userRoute(req: Request, res: Response) { // defining the route
res.json({
id: req.user!.id, // you tell typescript that req.user for sure not. null
username: req.user!.username, //
email: req.user!.email, //
role: req.user!.role, //
});
}
router.get("/user", checkIsAuthenticated, userRoute);
Комментарии:
1. Это сработает, но лучше всего избегать подобных утверждений.