【问题标题】:Arrange routes with authentication middleware使用身份验证中间件安排路由
【发布时间】:2016-08-30 03:54:00
【问题描述】:

我有很多路线。 他们中的大多数都需要身份验证。 一个没有。

他们在这里:

router.get('/secure1', function (req,res) {...})
router.get('/secure2', function (req,res) {...})
router.get('/secure3', function (req,res) {...})
router.get('/:id', function (req,res) {...})

1. 假设我没有公共路线。

我可以在页面顶部放置一个安全检查中间件,一切都很好。 它只会让安全连接通过,并且会重定向非安全连接。

router.use(function (req,res,next) {
   securityCheck()
   next()
})
router.get('/secure1', function (req,res) {...})
router.get('/secure2', function (req,res) {...})
router.get('/secure3', function (req,res) {...})
router.get('/:id', function (req,res) {...})

这会奏效。这使得所有安全路由都安全,但它阻止了我使用公共路由('/:id')。

2.我可以将公共路线移到顶部:

router.get('/:id', function (req,res) {...})
router.use(function (req,res,next) {
   securityCheck()
   next()
})
router.get('/secure1', function (req,res) {...})
router.get('/secure2', function (req,res) {...})
router.get('/secure3', function (req,res) {...})

但这样它会捕获我的所有请求,并且所有安全路径都无法访问。

3.我可以在每条安全路由上放置一个中间件,但这似乎有点乏味并且容易出现人为错误:

router.get('/secure1',securityCheck(), function (req,res) {...})

那么,我没有考虑过更好的选择吗?什么被认为是最佳实践?

谢谢

【问题讨论】:

    标签: node.js routes


    【解决方案1】:

    在您的选择中,我个人更喜欢第一个。在中间件中,您始终可以检查 req.pathreq.url 以选择要设置为安全的内容。

    另一种选择是使用 .htaccess 中的 HTTP 身份验证。看看https://github.com/http-auth/http-auth

    我之前进行身份验证的一种方法是将用户名/密码作为 json 传递给请求正文一次,然后为将来的请求生成一个无状态令牌 (https://github.com/auth0/node-jsonwebtoken)。在我的情况下,没有多少路由器条目需要身份验证,所以我自己处理条目。

    此外,为了提高安全性,请使用 HTTPS 或对您的数据进行编码。例如。 How to create an HTTPS server in Node.js?

    希望对您有所帮助!

    【讨论】:

    • 感谢您的回答!我同意,我觉得第一种方法是最容易维护的,人为错误会使某些东西公开看起来好像它是安全的,这比相反的方法要好。有了这个,如果有人请求最后一条路由,我如何告诉中间件继续?
    • 如果我是你,我会更好地区分非安全的(例如,可能类似于 /public/:id),因为这样你就不会将它与安全的混淆(从技术上讲,用户可能希望将 id 参数设置为字符串 secure3)。然后在中间件的开头你可以有: if(req.path starts with public) { next() } else { ... }
    • 当然有道理。事实上,我在我的应用程序的其他部分也这样做了。但是,在这种情况下,'/' 路由将指向用户的个人资料,而 '/otherThings' 是操纵个人资料的路由。我不想让配置文件有一个长地址,所以我不热衷于在这种情况下添加 /public/ 路由。
    • 那么在这种情况下,只需执行:if (not secure1, 2, 3) { next()} else {...}。或者只是正则表达式:)
    【解决方案2】:

    如果 /:id 应该匹配特定模式,比如 MongoDB ObjectId,您可以使匹配更加具体,这样它就不会匹配其他路由:

    router.get('/:id([a-fA-F0-9]{24})', function (req,res) {...})
    

    如果你想匹配 ObjectId 的 什么都没有,你可以使用这个:

    router.get('/:id(|[a-fA-F0-9]{24})', ...);
    

    更多信息herepath-to-regexp 是 Express 用来执行 URL 匹配的模块)。

    【讨论】:

    • 哇,太棒了!我不知道你能做到这一点!我怎样才能修复这个(正则表达式?)的东西,所以它接受 MongoDB ObjectId 或什么都不接受?意思是 '/ObjectID' 和 '/' 都将指向那里。 '/EverythingElse' 会导向其他地方吗?
    • 非常感谢!我赞成你的答案,我不能选择它作为正确的答案,因为它没有完全回答这个问题。有了这个,这是这个页面上最有用的东西。谢谢!
    • @MichaelSeltenreich 它将允许您在问题中使用解决方案 #2。
    • 我该怎么做?
    • 采取第二个解决方案(首先使用/:id 的路由,然后是router.use(...)),将/:id 替换为正则表达式,因此它只会匹配对有效ObjectId(或空请求)。任何其他请求都将传递给中间件并针对其他路由进行测试。
    猜你喜欢
    • 2018-07-25
    • 2018-12-27
    • 2016-05-10
    • 1970-01-01
    • 2019-12-11
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多