Node.js 使用Node和Express 4进行基本HTTP身份验证

Node.js 使用Node和Express 4进行基本HTTP身份验证,node.js,http,express,http-authentication,Node.js,Http,Express,Http Authentication,使用Express v3实现基本HTTP身份验证看起来很简单: app.use(express.basicAuth('username', 'password')); 但是,版本4(我使用的是4.2)删除了basicAuth中间件,所以我有点卡住了。我有以下代码,但它不会导致浏览器提示用户输入凭据,这正是我想要的(我想象旧方法会这样做): 我使用原始代码来找到答案: app.use(function(req, res, next) { var user = auth(req);

使用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.statusCode = 401;
        res.setHeader('WWW-Authenticate', 'Basic realm="MyRealmName"');
        res.end('Unauthorized');
    } else {
        next();
    }
});

在v4中,许多中间件从Express核心中抽出,并放入单独的模块中。基本身份验证模块如下所示:

您的示例只需更改为:

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

我在express 4.0中更改了基本身份验证,代码为:

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);

似乎有多个模块可以做到这一点,有些模块已被弃用

这一个看起来很活跃:

下面是一个使用示例:

// 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
中间件放在正确的位置,在此之前的任何中间件都不会经过身份验证。

Simple Basic auth with vanilla JavaScript(ES6) 注意:这个“中间件”可以在任何处理程序中使用。只需删除
next()
并反转逻辑即可。请参见下面的1-语句示例,或此答案的开头部分

为什么?
  • req.headers.authorization
    包含值“
    Basic
    ”,但它也可以是空的,我们不希望它失败,因此出现了一个奇怪的组合
  • 节点不知道
    atob()
    btoa()
    ,因此
ES6->ES5 只是
var
。。有点
只是
函数(x,y){…}

在一个系统中只有两个
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(/(.*?):(.*)/) || []
一条语句中的基本身份验证 …另一方面,如果您只使用一个或很少的登录,这是您需要的最低限度:(您甚至不需要解析凭据)


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


Express已删除此功能,现在建议您使用该库

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

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)
要向该路由发送请求,您需要包含一个格式化的for basic auth

首先发送curl请求,您必须采用
name:pass
的编码,或者在本例中为
aladdin:opensesame
,它等于
YWxhZGRpbjpvcGVuc2VzYW1l

然后,您的卷曲请求将如下所示:

 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);
资料来源:-

TL;博士: ☒ <代码>express.basicAuth不见了
☒ <代码>基本身份验证连接已弃用
☒ <代码>基本身份验证没有任何逻辑
☒ <代码>http身份验证是一种过度杀伤力
☑ <代码>快速基本身份验证是您想要的 更多信息: 既然您使用的是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!
}));
const-app=require('express')();
const basicAuth=require('express-basic-auth');
应用程序使用(basicAuth)({
用户:{admin:'supersecret123'},


挑战:正确//此模块声称已被弃用(尽管它建议的替代方案似乎不令人满意)^^绝对不令人满意,因为在密密麻麻的未记录文档中。作为中间件使用的示例为零,这可能很好,但调用不可用。他们给出的示例非常通用,但不适用于使用信息。是的,这一示例已被弃用,虽然推荐的示例文档数量较少,但代码非常简单,我已经介绍了如何使用e整个模块如何存在的
basic auth
库基于将密码以明文形式放在代码中??至少通过在base64中进行比较来模糊它似乎稍微好一点。此模块被认为已弃用,请改用(相同的api,因此答案仍然适用)实际上,我支持“基本身份验证连接”,名称不好,但从功能上看,它比“基本身份验证”好。后者所做的只是解析授权头。您仍然必须自己实现协议(也称为发送正确的头)太好了!谢谢你。这很有效,而且解释得很好。我试过了,但它一直要求我通过连续循环登录。最好的…:)不要使用
。split(':')
,因为它会阻塞至少包含一个冒号的密码。这样的密码根据有效。你也可以使用RegExp
const[\uz,login,password]=strauth.match(/(.*):(.*)/)|【】
用于冒号部分。使用
!==
比较密码容易受到定时攻击。请确保使用固定时间字符串比较。对于字符串
使用
缓冲区.from()//或对于数字
使用
缓冲区.alloc()//作为
缓冲区()
由于安全问题而被弃用。这实际上是即插即用。卓越。无耻的插件:我维护了一个相当流行的模块,使其变得简单,并具有您需要的最标准的功能:我最近分叉了@LionC的包,因为我必须对其进行调整(启用上下文感知授权程序)在公司项目的极短时间内:我花了一段时间才弄清楚挑战:真的option@VitaliiZurian很好的一点-我把它添加到了答案中。谢谢你指出它。@rsp你知道如何仅将它应用于特定的路由吗?如果你不想添加其他依赖项,用h编写基本的身份验证非常容易还有一句话…客户端url是什么样子的?希望它能解决这个问题,但请添加对代码的解释,这样用户就能完全理解他/她真正想要的。
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 -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);
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);