Node.js – 如何为不同的路由设置单独的身份validation?

我正在为Node.js开发一个使用basic-auth进行密码保护的项目。 目前,auth.js文件为所有路由提供相同的用户名/密码。 我将如何调整这个每个路线使用不同的用户名/密码?

auth.js文件:

const auth = require('basic-auth'); const username = 'admin'; const password = 'supersecret'; const internalIp = 'xxx.xx.xxx.xxx'; module.exports = function(app) { app.use((req, res, next) => { const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; // whitelist internal IP if (ip === internalIp) { next(); } else { const user = auth(req); if (user === undefined || user.name !== username || user.pass !== password) { // Return 401 error if user/pass is incorrect or empty res.statusCode = 401; res.setHeader('WWW-Authenticate', 'Basic realm="Research tool"'); res.end('Unauthorized'); } else { next(); } } }); }; 

app.js文件:

 var express = require('express'); var app = express(); var auth = require('./sources/auth.js'); // Run auth around app first auth(app); app.get('/route1', function(req, res) { res.render('pages/route1'); } app.get('/route2', function(req, res) { res.render('pages/route2'); } app.listen(port, function() { console.log('App listening on port: ' + port); }); 

运行:节点v6.11.1,express 4.13.4,basic-auth 1.1.0

你可以从app.js的请求对象中获取url,这样你就可以从文件或内部代码中包含route => credentials map。 然后你将能够遍历map来检查路由是否匹配传递的凭证数据。

你有用户名和密码硬编码是非常不寻常的。更典型的是用户名和(散列)密码存储在数据库中。 然后,当一个授权请求进来时,你使用用户名来获取密码,并将两个密码相互比较。 这样,一个auth中间件可以服务任意数量的用户名/密码组合。

也就是说,如果你真的需要两个独立的auth中间件,更好的方法是将所需的中间件插入到每个路由中。 像这样的东西:

auth.js

 const auth = require('basic-auth') const getAuthorizer = (name, pass) => (req, res, next) => { const user = auth(req) if (!user || user.name !== name || user.pass !== pass) { res.status(401).send('Unauthorized') } else { next() } } const admin = getAuthorizer('admin', 'supersecret') const user = getAuthorizer('user', '12345') module.exports = { admin, user } 

app.js

 const express = require('express') const app = express() const auth = require('./sources/auth') app.get('/route1', auth.admin, (req, res) => { res.render('pages/route1') }) app.get('/route2', auth.user, (req, res) => { res.render('pages/route2') }) app.listen(port, () => { console.log('App listening on port: ' + port) })