Express中间件两种认证写法对比:哪种更优及原因?
推荐哪种Express认证中间件写法?
先把两种实现方式明确列出来:
方式一:直接通过router.use挂载全局中间件
router.use((req, res, next) => { // 作为单个路由导出到文件中 if (req.isAuthenticated()) { next(); return; } res.sendStatus(401); });
方式二:封装为独立命名函数
const authenticate = (req, res, next) => { if (req.isAuthenticated()) { next(); return; } res.sendStatus(401); }; // 使用示例 router.post('/', authenticate, (req, res, next) => {});
毫无疑问,第二种封装成命名函数的写法更值得推荐,核心原因如下:
复用性更灵活:第一种写法会强制给当前
router下的所有路由加上认证逻辑,要是这个路由文件里存在不需要认证的公开接口(比如首页查询、验证码接口),这种写法就直接失效了。而命名函数的方式可以按需给单个/部分路由添加认证,不管是同一个router还是不同的路由模块,都能直接调用,适配更多场景。可读性与可维护性更强:
authenticate这个名字直接点明了函数作用,其他开发者看代码时一眼就能理解这个中间件的用途。后续如果要修改认证逻辑(比如新增权限校验、调整错误返回格式),只需要修改这一个函数即可,不用在各个router.use的位置到处找代码。测试成本更低:独立的命名函数可以脱离Express环境做单元测试,你只需要模拟
req、res、next对象,就能验证认证逻辑的正确性,不需要启动整个服务,测试效率高很多。扩展能力拉满:如果后续需要区分不同权限的认证(比如普通用户、管理员),可以轻松改造成高阶函数:
const authenticate = (requiredRole) => { return (req, res, next) => { if (req.isAuthenticated() && req.user.role === requiredRole) { next(); return; } res.sendStatus(requiredRole ? 403 : 401); }; }; // 使用示例:管理员专属接口 router.post('/admin/dashboard', authenticate('admin'), (req, res) => {});这种扩展能力是第一种写法完全无法实现的。
当然第一种写法也有适用场景:如果某个路由模块下的所有接口都必须认证,直接用router.use挂载确实省事,但这种场景相对有限,绝大多数业务场景下,第二种写法的通用性和灵活性都更优。
内容的提问来源于stack exchange,提问作者Avery235
相关产品推荐
相关产品推荐

