node.js - 如何使用 JWT 在 Express 中为单个路由(无代码重复)验证多种类型用户的身份验证 token ?

标签 node.js express jwt

我有一个快速应用程序,其中一些路线是公开的(互联网上的每个人都可以访问),而有些路线受到保护。我使用 JWT 进行路由认证。我在系统中有不同类型的用户,例如:作者、订阅者等。有些路由是访问作者,有些是订阅者。但是有一些路由可供作者和订阅者访问。
为了确保当用户请求 protected 路由时,我对每一类用户使用中间件功能来验证他们的身份验证 token 。
仅像下面这样的作者可以访问的示例路线,

router.get("/", verifyToken.author(), async (req, res) => {
    try {
        // doing stuff
    } catch (err) {
        // doing stuff
    }
});
订阅者只能访问的示例路线,如下所示,
router.get("/", verifyToken.subscriber(), async (req, res) => {
    try {
        // doing stuff
    } catch (err) {
        // doing stuff
    }
});
PS:verifyToken.author()或者我为验证 token 而编写的任何其他中间件函数实际上是闭包。因为有时我需要在函数中传递参数。所以,这些方法的一个例子是,
module.exposts.author = () => {
    return (req, res, next) => {
        const token = req.header("Authorization");
        if (!token) return res.status(401).send({ message: "Access Denied!" });

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

            next();
        } catch (err) {
            res.status(401).send({ message: "Access Denied!" });
            console.log(err);
        }
    };
};
当我需要编写一个函数来验证作者和订阅者的 token 时,我可以检查这样做并将该方法用作所需路由的中间件。但恐怕这并不像听起来那么简单,因为实际上我不只有这两种类型的用户。并且几乎所有用户类型都有复杂的路由访问,其中可能有 5 个特定类型的用户可以访问该路由。
正如我所说,假设作者和订阅者属于我上面所说的 5 种用户类型。因此,为作者+订阅者编写一个函数,并为作者、订阅者存在的 5 种类型的用户编写另一个函数,似乎代码重复太多。
我希望我能解释为什么我不想写这样的东西,
module.exports.authorSubscriber = () => {
    return (req, res, next) => {
        const token = req.header("Authorization");
        if (!token) return res.status(401).send({ message: "Access Denied!" });

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

            next();
        } catch (err) {
            try {
                jwt.verify(token, process.env.SUBSCRIBER_SECRET);
    
                next();
            } catch (err) {
                res.status(401).send({ message: "Access Denied!" });
                console.log(err);
            }
        }
    };
};
相反,我想要这样的东西,在那里我可以重用我之前为作者编写的函数,
module.exports.authorSubscriber = () => {
    return (req, res, next) => {
        const token = req.header("Authorization");
        if (!token) return res.status(401).send({ message: "Access Denied!" });

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

            next();
        } catch (err) {
            exports.author()
        }
    };
};
但是,author()不会在这里工作。它在从路由调用时工作,因为它会得到 req, res, next .但是在这种情况下,它是从另一个函数调用的,并且没有传递 req, res, next 。如果我这样做 exports.author(req, res, next)authorSubscriber并定义作者接受这些参数。它仍然不起作用。我认为路由中间件会自动获取“req、res、next”,这些东西不能手动传递,是吗?这就是我关闭这些函数的原因,因为在类似的验证器上,我需要传递某个 token ,而中间件不需要额外的参数。
我很迷惑。您可能已经清楚地意识到我有知识差距,这就是为什么我在这里遗漏了一些东西。
请帮忙。

最佳答案

假设您在闭包中定义“作者”中间件,如上面的示例所示:

module.exposts.author = () => {
    return (req, res, next) => {
        // implementation here
    };
};
然后您确实可以在您描述的“作者+订阅者”场景中重新使用它。但请记住,上面定义的中间件不是名为 author 的函数。 ;相反,中间件是从名为 author 的函数返回的匿名函数。 .所以如果你想在 authorSubscriber 中重用它,它看起来像:
module.exports.authorSubscriber = () => {
    return (req, res, next) => {
        // ...
        try {
            jwt.verify(token, process.env.AUTHOR_SECRET);

            next();
        } catch (err) {
            exports.author()(req, res, next)
        }
    };
};
请注意,您正在拨打 exports.author()首先,它将返回对内部函数的引用,该函数是您实际要调用的中间件。
正如其他评论所指出的那样,这种类型的访问控制可能有更好的模式,您可以在 future 转向,但如果您的目标只是重用您已经在不同上下文中定义的中间件,我认为这似乎可行。

关于node.js - 如何使用 JWT 在 Express 中为单个路由(无代码重复)验证多种类型用户的身份验证 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67739799/

相关文章:

c# - IDX10603 : The algorithm: 'HS256' requires the SecurityKey. KeySize 大于 '128' 位。 KeySize 报告 : '32' . 参数名称 : key. KeySize

node.js - NodeJS、作业调度

javascript - 在 nodejs 中 'inspect' 就像一个保留字

reactjs - 超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

linux - Spring Security getprincipal() 方法返回字符串(用户名)代替类 UserDetails

javascript - 无状态JSON Web token 中存储的内容

javascript - Selenium WebDriver findElements 返回对象

node.js - 哎呀!我想我破坏了我的工作环境(nvm、npm 和 Node w/Angular)。 :(

javascript - 如何使用快速 session 作为身份验证处理程序

javascript - 如何将一个 POST 请求转发到两个外部 url?