Каков наилучший способ проверки токена аутентификации разных типов пользователей?

#node.js #express #jwt

#node.js #экспресс #jwt

Вопрос:

Допустим, у меня есть 10 маршрутов, и каждый маршрут доступен только для определенного типа пользователей. Когда пользователь входит в систему, генерируется токен.Эти пользовательские токены генерируются с их _id и секретным токеном, который хранится в .env файле.

Обычно проверка токена для каждого типа пользователя выполняется с помощью отдельных функций, поскольку у разных типов пользователей разные секреты токена. Например, возможно, секрет токена user1 TOKEN_SECRET_USER2 = 6ygfewf6hj и, возможно, токен user2 TOKEN_SECRET_USER1 = 87uhjkaf89 .

И когда какой-либо запрос отправляется на маршрут, проверяется токен пользователя, чтобы узнать, может ли пользователь получить доступ к этому маршруту или нет.

Вот два примера маршрута, доступных для разных типов пользователей,

 // Route accessible to user type 1
router.get("/foo", verifyTokenUSER1, async (req, res) => {
    // All the good stuff
});

// Route accessible to user type 2
router.post("/bar", verifyTokenUSER2, async (req, res) => {
    // All the good stuff
});
 

Вот какой-то метод проверки модуля выглядит следующим образом,

 // Verification for user 1
const verifyTokenUSER1 = (req, res, next) => {

    const token = req.header("auth-token");
    if (!token) return res.status(401).send();

    try {
        jwt.verify(token, process.env.TOKEN_SECRET_USER1);

        next();
    } catch (err) {
        res.status(401).send();
    }
};

// Verification for user 2
const verifyTokenUSER2 = (req, res, next) => {

    const token = req.header("auth-token");
    if (!token) return res.status(401).send();

    try {
        jwt.verify(token, process.env.TOKEN_SECRET_USER2);

        next();
    } catch (err) {
        res.status(401).send();
    }
};
 

Как вы можете видеть, в приведенных выше методах есть только одно изменение, которое является секретом токена доступа для типов пользователей.

Я хотел бы проверить их, используя 1 (одну) единственную функцию, если это возможно. Но я не могу передать какое-либо значение в качестве параметра методам проверки. Итак, как я могу устранить дублирование здесь?

Ответ №1:

На самом деле вы можете передать параметр методу проверки, если используете bind (mdn):

 // Route accessible to user type 1
router.get("/foo", verifyToken.bind(null, process.env.TOKEN_SECRET_USER1), async (req, res) => {
    // All the good stuff
});

// Route accessible to user type 2
router.post("/bar", verifyToken.bind(null, process.env.TOKEN_SECRET_USER2), async (req, res) => {
    // All the good stuff
});
 

bind метод функции здесь получает 2 параметра: во-первых, this контекст для функции, а во-вторых, первый аргумент. Он возвращает новую функцию, которая получит предоставленный токен в качестве первого аргумента и получит req, res, next в качестве следующих аргументов.

 const verifyToken = (tokenSecret, req, res, next) => {

    const token = req.header("auth-token");
    if (!token) return res.status(401).send();

    try {
        jwt.verify(token, tokenSecret);

        next();
    } catch (err) {
        res.status(401).send();
    }
};
 

Другим эквивалентным способом сделать это является создание метода проверки «factory», который возвращает функцию проверки, которая имеет замыкание (mdn) на токене:

 
// Route accessible to user type 1
router.get("/foo", getTokenVerifier(process.env.TOKEN_SECRET_USER1), async (req, res) => {
    // All the good stuff
});

// Route accessible to user type 2
router.post("/bar", getTokenVerifier(process.env.TOKEN_SECRET_USER2), async (req, res) => {
    // All the good stuff
});

// this function returns a new function, with a closure on the provided tokenSecret
const getTokenVerifier = (tokenSecret) => {
  return (req, res, next) => {
    const token = req.header("auth-token");
    if (!token) return res.status(401).send();

    try {
        jwt.verify(token, tokenSecret);

        next();
    } catch (err) {
        res.status(401).send();
    }
  }

}