Arrange routes with authentication middleware

2020-07-30 01:57发布

问题:

I have many routes. Most of them require authentication. One doesn't.

Here they are:

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. Let's imagine I didn't have the public route.

At the top of the page I could just put a security check middleware, and all is well. It will only let through secure connections, and will redirect non secure.

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) {...})

This would work. this makes all the secure routes secure, but it blocks me from the public route ('/:id').

2. I could move the public route to the top:

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) {...})

But this way it catches all of my requests and all the secure paths are inaccessible.

3. I could put a middleware on every single secure route, but that seems a little tedious and prone to human-errors:

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

So, is there a better option I didn't consider? What is considered the best practice?

Thank you

回答1:

Out of your options I would personally prefer the first one. In the middleware you can always check on req.path or req.url to choose what to set as secure.

Another option is using HTTP authentication like in .htaccess. Have a look at https://github.com/http-auth/http-auth.

A way I have done authentication before was by passing username/password over the request body as json once and then producing a stateless Token for future requests (https://github.com/auth0/node-jsonwebtoken). In my case not many router entries needed authentication, so I handled it on the entries themselves.

Also, for extra security, use HTTPS or encode your data. Eg. How to create an HTTPS server in Node.js?

Hope it helped!



回答2:

If /:id should match a particular pattern, say a MongoDB ObjectId, you can make the match more specific so it won't match the other routes:

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

If you want to match ObjectId's or nothing, you can use this:

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

More information here (path-to-regexp is the module that Express uses to perform URL matching).