Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由
Posted
技术标签:
【中文标题】Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由【英文标题】:Passport Authentication Middleware for Node/Express - How to Protect all Routes 【发布时间】:2021-12-06 23:41:34 【问题描述】:堆栈:
前端 - Angular 12
|-- 利用 Angular/MSAL 与 Azure AD 集成 身份验证
后端:
|-- 节点JS V14.17.6 |-- Express 4.17.1 |-- 护照-Azure-AD V4.3.0(passport-azure-ad 是 Passport Strategies 的集合 帮助
您与 Azure Active 集成 |-- 身份验证策略 - BearerStrategy(保护 API 和资源) 目录) |-- Passport V0.3.2(Passport-Azure-AD 使用的 Passport 版本)
后端项目结构(为简洁起见摘录) 根目录 |-- 源 |-- 路由器(在单个 .js 文件中保存每个实体的所有模块化路由的子目录,例如 users.js、actions.js) |--index.js(应用入口点)
我正在寻找一种方法来保护我的所有路由/api端点,而不是必须将passport.authenticate应用于每个路由端点内的每个路由处理程序,这可能是每个模块化路由的“N”个路由.js 文件,如上所述。我尝试了以下方法无济于事。
在 index.js 文件中,即我使用的应用程序入口点,例如const users = require('./routers/users') 和 app.use('/api/v1/users', users) 来挂载我的路由处理程序,我介绍了以下 app.use(passport.authenticate('oauth- Bearer', session: false )) 因为护照是一个中间件但没有乐趣
在模块化路由处理文件中,我也尝试了以下方法: router.all('*'
,passport.authenticate('oauth-bearer', session: false )) 基于快速文档 router.所有人都应该在所有请求方法的路径上应用中间件或提供的函数/处理程序,在这种情况下,'*'
应该匹配所有路径,但这仍然只适用于基本路径“/”而不适用于文件中的其他路径,例如'/关系'
如果有人能开出保护所有路线的方法,将不胜感激。
【问题讨论】:
【参考方案1】:router.all()
函数与 router.METHOD() 方法类似,只是它匹配所有 HTTP 方法(动词)。
如果我写,router.all('/users', callback)
,这意味着回调将为端点/users
的每个方法(GET、POST、DELETE、PATCH、PUT 等)运行。
如果想为每条路线运行它,你需要做这样的事情 -
router.all('*', callback)
-
我喜欢使用
router.use()
函数,该函数专门针对此类用例。假设我的监控路由中有 2 个端点。如果我想为两者都设置身份验证保护,我喜欢这样做 -
const constant = require(__basePath + 'app/config/constant');
const router = require('express').Router(
caseSensitive: true,
strict : true
);
const monitor = require(constant.path.module + 'monitor/monitor.controller');
const Passport = require('passport');
const AuthGuard = Passport.authenticate(['user', 'admin'], session : false );
router.use(AuthGuard);
router.get(
'/ping',
monitor.ping
);
router.get(
'/status',
monitor.status
);
module.exports =
router: router
;
附: - 请忽略constant
和path
相关的东西,仅供参考。
【讨论】:
您好 Pankaj,感谢您抽出宝贵时间回答我的问题。因此,谈到 Router 实例的“all”方法,我确实熟悉它的功能。我想指出您对 passport.authenticate 的使用,不确定这是错误还是无意的遗漏;注意到您没有提供所需的第一个参数,即护照策略,因此在我的情况下,这将是一个承载策略,因为我严格需要保护资源/api 端点。如果没有提供的策略,您的上述实现将导致错误 嗨@nubianMONK,我使用的这两个策略(['user', 'admin'],
,是在一个单独的护照服务文件中定义的(在主服务器文件中导入和初始化)。我只是想解释一下我如何使用router.use()
。【参考方案2】:
所以在寻找解决方案多天后,我终于找到了为什么我的上述实施不起作用的罪魁祸首。它归结为最近引入的通配符'*'
功能,因为它适用于 MSAL/Angular 的 protectedResourceMap。利用上面的示例,从客户端(Angular V12)实现的方式是将上述受保护的资源映射设置为:'http://localhost:3001/api/v1/*',这在逻辑上会很好转保护端点,例如
-
'http://localhost:3001/api/v1/users'
'http://localhost:3001/api/v1/users/relationshp'
但我发现通配符并不像人们想象的那样工作,它几乎只会匹配上面标记为 (1.) 的第一个 url,因为这是在“users.js”路由器文件中处理的路由器处理程序,基本端点 router.get('/', (req, res, next) => ...do something );并将完全抛弃以下路由器处理程序(应匹配上面标记为 (2.) 的第二个 url),端点 router.get('/relationships', (req, res, next) => ...do something );顺便说一句,它同样在“users.js”路由器文件中实现。
节省一天客户端修复(Angular V12)的解决方案是首先删除通配符 asterix '*'
作为受保护资源映射配置的一部分,并保持原样:'http://localhost:3001/api /v1/' 并根据我的要求在服务器端(NodeJs),即保护所有路由是将以下解决方案应用于服务器解决方案“index.js”的入口点,利用护照作为全面应用于应用程序的中间件: app.use(passport.authenticate('oauth-bearer', session: false ));这种方式不需要在每个路由器处理程序文件中实现相同的。希望这对面临类似问题的人们有所帮助。
【讨论】:
以上是关于Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由的主要内容,如果未能解决你的问题,请参考以下文章
Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由
Node、Express、Oauth2 和 Passport 的 Angularjs CORS 问题
在 JWT 中存储秘密信息,使用 Node.js - Express 后端
无法读取 null + passport.js 的属性“正文”
Passportjs Facebook 登录流程(passport-facebook vs passport-token)