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

时间:2014-05-12 18:37:46

标签: 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);

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

9 个答案:

答案 0 :(得分:74)

使用vanilla 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] = new Buffer(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()并反转逻辑。请参阅下面的 1-statement 示例或此答案的edit history

为什么?

  • req.headers.authorization包含值&#34; Basic <base64 string>&#34;,但它也可以为空,我们不希望它失败,因此{{{{{{ 1}}
  • 节点不知道|| ''atob(),因此Buffer

ES6 - &gt; ES5

const只是btoa() ..有点像 (x, y) => {...}只是var const [login, password] = ...split()在一个

中只有两个function(x, y) {...}分配

source of inspiration (uses packages)

<小时/> 以上是超级简单示例,旨在超短并可快速部署到您的游乐场服务器。但正如评论中指出的那样,密码也可以包含冒号字符var。要从 b64auth 中正确提取它,您可以使用它。

:

一个语句中的基本身份验证

...另一方面,如果你只使用一次或几次登录,这是你需要的最低限度:(你根本不需要解析凭证)< / em>的

  // parse login and password from headers
  const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
  const strauth = new Buffer(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:你需要同时拥有&#34; secure&#34;和#34;公共&#34;路径?请考虑使用express.router代替。

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

答案 1 :(得分:58)

许多中间件在v4中被拉出了Express核心,并被放入了单独的模块中。基本身份验证模块位于:https://github.com/expressjs/basic-auth-connect

您的示例只需要更改为:

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

答案 2 :(得分:38)

TL; DR:

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

答案 3 :(得分:33)

我使用原始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();
    }
});

答案 4 :(得分:32)

我在快递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);

答案 5 :(得分:19)

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

这个看起来很活跃:
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中间件放在正确的位置,之前的任何中间件都不会通过身份验证。

答案 6 :(得分:4)

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

null

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

答案 7 :(得分:1)

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)

要向此路线发送请求,您需要包含格式化为基本身份验证的Authorization header

首先发送卷曲请求您必须采用name:pass的{​​{3}}编码,或者aladdin:opensesame YWxhZGRpbjpvcGVuc2VzYW1l等于 curl -H "Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l" http://localhost:3000/

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

{{1}}

答案 8 :(得分:0)

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