使用 Node 和 Express4的基本 HTTP 身份验证

使用 Express v3实现基本的 HTTP 身份验证看起来很简单:

app.use(express.basicAuth('username', 'password'));

版本4(我使用的是4.2)删除了 basicAuth中间件,所以我有点卡住了。我有以下代码,但它不会导致浏览器提示用户输入凭据,这正是我所希望的(我想这也是旧方法所做的) :

app.use(function(req, res, next) {
var user = auth(req);


if (user === undefined || user['name'] !== 'username' || user['pass'] !== 'password') {
res.writeHead(401, 'Access invalid for user', {'Content-Type' : 'text/plain'});
res.end('Invalid credentials');
} else {
next();
}
});
173688 次浏览

我用原始 basicAuth的代码找到了答案:

app.use(function(req, res, next) {
var user = auth(req);


if (user === undefined || user['name'] !== 'username' || user['pass'] !== 'password') {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="MyRealmName"');
res.end('Unauthorized');
} else {
next();
}
});

在 v4中,许多中间件从 Express 核心中提取出来,放到单独的模块中。基本的 auth 模块在这里: https://github.com/expressjs/basic-auth-connect

你的例子需要改成这样:

var basicAuth = require('basic-auth-connect');
app.use(basicAuth('username', 'password'));

我在 Express 4.0中改变了 http-auth的基本认证,代码是:

var auth = require('http-auth');


var basic = auth.basic({
realm: "Web."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "userName" && password === "password");
}
);


app.get('/the_url', auth.connect(basic), routes.theRoute);

似乎有多个模块可以做到这一点,其中一些是不推荐的。

这个看起来很活跃:
Https://github.com/jshttp/basic-auth

下面是一个使用例子:

// auth.js


var auth = require('basic-auth');


var admins = {
'art@vandelay-ind.org': { password: 'pa$$w0rd!' },
};




module.exports = function(req, res, next) {


var user = auth(req);
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
res.set('WWW-Authenticate', 'Basic realm="example"');
return res.status(401).send();
}
return next();
};








// app.js


var auth = require('./auth');
var express = require('express');


var app = express();


// ... some not authenticated middlewares


app.use(auth);


// ... some authenticated middlewares

确保您将 auth中间件放在正确的位置,在此之前的任何中间件都不会被验证。

使用普通 JavaScript (ES6)的简单基本认证

app.use((req, res, next) => {


// -----------------------------------------------------------------------
// authentication middleware


const auth = {login: 'yourlogin', password: 'yourpassword'} // change this


// parse login and password from headers
const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':')


// Verify login and password are set and correct
if (login && password && login === auth.login && password === auth.password) {
// Access granted...
return next()
}


// Access denied...
res.set('WWW-Authenticate', 'Basic realm="401"') // change this
res.status(401).send('Authentication required.') // custom message


// -----------------------------------------------------------------------


})

注意: 这个“中间件”可以在任何处理程序中使用。只要删除 next()并逆转逻辑。请参阅下面的 一句话例子,或者这个答案的 编辑历史

为什么?

  • req.headers.authorization包含值“ Basic <base64 string>”,但它也可以是空的,我们不希望它失败,因此 || ''的奇怪组合
  • 节点不知道 atob()btoa(),因此使用 Buffer

ES6-> ES5

const 只是 var. . 排序
就是 function(x, y) {...}
const [login, password] = ...split() 只是一个作业中的两个 var作业

灵感来源(使用软件包)


上面是一个 超级简单示例,它是 超级短,可以快速部署到您的操场服务器上。但是正如在评论中指出的,密码也可以包含冒号字符 :。要正确地从 B64auth中提取它,可以使用。

  // parse login and password from headers
const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
const strauth = Buffer.from(b64auth, 'base64').toString()
const splitIndex = strauth.indexOf(':')
const login = strauth.substring(0, splitIndex)
const password = strauth.substring(splitIndex + 1)


// using shorter regex by @adabru
// const [_, login, password] = strauth.match(/(.*?):(.*)/) || []

一个语句中的基本认证

... 另一方面,如果您只使用一个或很少的登录,这是您需要的最低限度: (您甚至根本不需要解析凭据)

function (req, res) {
//btoa('yourlogin:yourpassword') -> "eW91cmxvZ2luOnlvdXJwYXNzd29yZA=="
//btoa('otherlogin:otherpassword') -> "b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk"


// Verify credentials
if (  req.headers.authorization !== 'Basic eW91cmxvZ2luOnlvdXJwYXNzd29yZA=='
&& req.headers.authorization !== 'Basic b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk')
return res.status(401).send('Authentication required.') // Access denied.


// Access granted...
res.send('hello world')
// or call next() if you use it as middleware (as snippet #1)
}

PS: 您需要同时拥有“安全”和“公共”路径吗? 请考虑使用 express.router

var securedRoutes = require('express').Router()


securedRoutes.use(/* auth-middleware from above */)
securedRoutes.get('path1', /* ... */)


app.use('/secure', securedRoutes)
app.get('public', /* ... */)


// example.com/public       // no-auth
// example.com/secure/path1 // requires auth

Express 已经删除了这个功能,现在建议您使用 Basic-auth库。

下面是一个如何使用的例子:

var http = require('http')
var auth = require('basic-auth')


// Create server
var server = http.createServer(function (req, res) {
var credentials = auth(req)


if (!credentials || credentials.name !== 'aladdin' || credentials.pass !== 'opensesame') {
res.statusCode = 401
res.setHeader('WWW-Authenticate', 'Basic realm="example"')
res.end('Access denied')
} else {
res.end('Access granted')
}
})


// Listen
server.listen(3000)

要向此路由发送请求,您需要包括一个为基本身份验证格式化的 授权头

首先发送一个 curl 请求,您必须采用 name:pass基地64编码,或者在这种情况下采用等于 YWxhZGRpbjpvcGVuc2VzYW1laladdin:opensesame编码

你的卷曲请求看起来就像:

 curl -H "Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l" http://localhost:3000/

我们可以在不需要任何模块的情况下实现基本的授权

//1.
var http = require('http');


//2.
var credentials = {
userName: "vikas kohli",
password: "vikas123"
};
var realm = 'Basic Authentication';


//3.
function authenticationStatus(resp) {
resp.writeHead(401, { 'WWW-Authenticate': 'Basic realm="' + realm + '"' });
resp.end('Authorization is needed');


};


//4.
var server = http.createServer(function (request, response) {
var authentication, loginInfo;


//5.
if (!request.headers.authorization) {
authenticationStatus (response);
return;
}


//6.
authentication = request.headers.authorization.replace(/^Basic/, '');


//7.
authentication = (new Buffer(authentication, 'base64')).toString('utf8');


//8.
loginInfo = authentication.split(':');


//9.
if (loginInfo[0] === credentials.userName && loginInfo[1] === credentials.password) {
response.end('Great You are Authenticated...');
// now you call url by commenting the above line and pass the next() function
}else{


authenticationStatus (response);


}


});
server.listen(5050);

资料来源:-http://www.dotnetcurry.com/nodejs/1231/basic-authentication-using-nodejs

译者:

express.basicAuth消失了 basic-auth-connect不被推崇 basic-auth没有任何逻辑 http-auth是一个过度杀伤 express-basic-auth就是你想要的

更多信息:

因为您使用 Express,所以可以使用 express-basic-auth中间件。

查看文件:

例如:

const app = require('express')();
const basicAuth = require('express-basic-auth');
 

app.use(basicAuth({
users: { admin: 'supersecret123' },
challenge: true // <--- needed to actually show the login dialog!
}));
function auth (req, res, next) {
console.log(req.headers);
var authHeader = req.headers.authorization;
if (!authHeader) {
var err = new Error('You are not authenticated!');
res.setHeader('WWW-Authenticate', 'Basic');
err.status = 401;
next(err);
return;
}
var auth = new Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':');
var user = auth[0];
var pass = auth[1];
if (user == 'admin' && pass == 'password') {
next(); // authorized
} else {
var err = new Error('You are not authenticated!');
res.setHeader('WWW-Authenticate', 'Basic');
err.status = 401;
next(err);
}
}
app.use(auth);

安装 Express-basic-auth 依赖项:

 npm i express-basic-auth

需要您创建应用程序的认证包

const app = require('express')();
const basicAuth = require('express-basic-auth');

然后像这样设置中间件:

app.use(basicAuth({
users: { 'my-username': 'my-password' },
challenge: true,
}));